diff options
Diffstat (limited to 'app')
39 files changed, 224 insertions, 293 deletions
diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js index e9d6d121e6d..9463286e53e 100644 --- a/app/assets/javascripts/analytics/shared/constants.js +++ b/app/assets/javascripts/analytics/shared/constants.js @@ -20,10 +20,13 @@ const formatDateParam = (d) => dateFormat(d, dateFormats.isoDate, true); export const METRIC_POPOVER_LABEL = s__('ValueStreamAnalytics|View details'); -export const KEY_METRICS = { +export const ISSUES_COMPLETED_TYPE = 'issues_completed'; + +export const FLOW_METRICS = { LEAD_TIME: 'lead_time', CYCLE_TIME: 'cycle_time', ISSUES: 'issues', + ISSUES_COMPLETED: ISSUES_COMPLETED_TYPE, COMMITS: 'commits', DEPLOYS: 'deploys', }; @@ -38,7 +41,7 @@ export const DORA_METRICS = { const VSA_FLOW_METRICS_GROUP = { key: 'key_metrics', title: s__('ValueStreamAnalytics|Key metrics'), - keys: Object.values(KEY_METRICS), + keys: Object.values(FLOW_METRICS), }; export const VSA_METRICS_GROUPS = [VSA_FLOW_METRICS_GROUP]; @@ -90,7 +93,7 @@ export const METRIC_TOOLTIPS = { projectLink: '-/pipelines/charts?chart=change-failure-rate', docsLink: helpPagePath('user/analytics/dora_metrics', { anchor: 'change-failure-rate' }), }, - [KEY_METRICS.LEAD_TIME]: { + [FLOW_METRICS.LEAD_TIME]: { description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'), groupLink: '-/analytics/value_stream_analytics', projectLink: '-/value_stream_analytics', @@ -98,7 +101,7 @@ export const METRIC_TOOLTIPS = { anchor: 'view-the-lead-time-and-cycle-time-for-issues', }), }, - [KEY_METRICS.CYCLE_TIME]: { + [FLOW_METRICS.CYCLE_TIME]: { description: s__( "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.", ), @@ -108,13 +111,21 @@ export const METRIC_TOOLTIPS = { anchor: 'view-the-lead-time-and-cycle-time-for-issues', }), }, - [KEY_METRICS.ISSUES]: { + [FLOW_METRICS.ISSUES]: { description: s__('ValueStreamAnalytics|Number of new issues created.'), groupLink: '-/issues_analytics', projectLink: '-/analytics/issues_analytics', docsLink: helpPagePath('user/analytics/issue_analytics'), }, - [KEY_METRICS.DEPLOYS]: { + [FLOW_METRICS.ISSUES_COMPLETED]: { + description: s__('ValueStreamAnalytics|Number of issues closed by month.'), + groupLink: '-/analytics/value_stream_analytics', + projectLink: '-/value_stream_analytics', + docsLink: helpPagePath('user/analytics/value_streams_dashboard', { + anchor: 'dashboard-metrics-and-drill-down-reports', + }), + }, + [FLOW_METRICS.DEPLOYS]: { description: s__('ValueStreamAnalytics|Total number of deploys to production.'), groupLink: '-/analytics/productivity_analytics', projectLink: '-/analytics/merge_request_analytics', diff --git a/app/assets/javascripts/ci/artifacts/components/artifact_row.vue b/app/assets/javascripts/ci/artifacts/components/artifact_row.vue index 5b1c322f07a..d4de42b10a8 100644 --- a/app/assets/javascripts/ci/artifacts/components/artifact_row.vue +++ b/app/assets/javascripts/ci/artifacts/components/artifact_row.vue @@ -8,12 +8,10 @@ import { GlTooltipDirective, } from '@gitlab/ui'; import { numberToHumanSize } from '~/lib/utils/number_utils'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { I18N_EXPIRED, I18N_DOWNLOAD, I18N_DELETE, - BULK_DELETE_FEATURE_FLAG, I18N_BULK_DELETE_MAX_SELECTED, } from '../constants'; @@ -29,7 +27,6 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - mixins: [glFeatureFlagsMixin()], inject: ['canDestroyArtifacts'], props: { artifact: { @@ -66,7 +63,7 @@ export default { return numberToHumanSize(this.artifact.size); }, canBulkDestroyArtifacts() { - return this.glFeatures[BULK_DELETE_FEATURE_FLAG] && this.canDestroyArtifacts; + return this.canDestroyArtifacts; }, }, methods: { diff --git a/app/assets/javascripts/ci/artifacts/components/job_artifacts_table.vue b/app/assets/javascripts/ci/artifacts/components/job_artifacts_table.vue index 81739db9be2..88334488fdd 100644 --- a/app/assets/javascripts/ci/artifacts/components/job_artifacts_table.vue +++ b/app/assets/javascripts/ci/artifacts/components/job_artifacts_table.vue @@ -15,7 +15,6 @@ import { createAlert } from '~/alert'; import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { TYPENAME_PROJECT } from '~/graphql_shared/constants'; import getJobArtifactsQuery from '../graphql/queries/get_job_artifacts.query.graphql'; import { totalArtifactsSizeForJob, mapArchivesToJobNodes, mapBooleansToJobNodes } from '../utils'; @@ -39,7 +38,6 @@ import { INITIAL_NEXT_PAGE_CURSOR, JOBS_PER_PAGE, INITIAL_LAST_PAGE_SIZE, - BULK_DELETE_FEATURE_FLAG, I18N_BULK_DELETE_ERROR, I18N_BULK_DELETE_PARTIAL_ERROR, I18N_BULK_DELETE_CONFIRMATION_TOAST, @@ -83,7 +81,6 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - mixins: [glFeatureFlagsMixin()], inject: ['projectId', 'projectPath', 'canDestroyArtifacts'], apollo: { jobArtifacts: { @@ -161,7 +158,7 @@ export default { return this.selectedArtifacts.length >= SELECTED_ARTIFACTS_MAX_COUNT; }, canBulkDestroyArtifacts() { - return this.glFeatures[BULK_DELETE_FEATURE_FLAG] && this.canDestroyArtifacts; + return this.canDestroyArtifacts; }, isDeletingArtifactsForJob() { return this.jobArtifactsToDelete.length > 0; diff --git a/app/assets/javascripts/ci/artifacts/constants.js b/app/assets/javascripts/ci/artifacts/constants.js index 4fb4b45fd7f..2d89b6541f3 100644 --- a/app/assets/javascripts/ci/artifacts/constants.js +++ b/app/assets/javascripts/ci/artifacts/constants.js @@ -54,7 +54,6 @@ export const I18N_FEEDBACK_BANNER_BODY = s__( export const I18N_FEEDBACK_BANNER_BUTTON = s__('Artifacts|Take a quick survey'); export const FEEDBACK_URL = 'https://gitlab.fra1.qualtrics.com/jfe/form/SV_cI9rAUI20Vo2St8'; -export const BULK_DELETE_FEATURE_FLAG = 'ciJobArtifactBulkDestroy'; export const SELECTED_ARTIFACTS_MAX_COUNT = 50; export const I18N_BULK_DELETE_MAX_SELECTED = s__( 'Artifacts|Maximum selected artifacts limit reached', diff --git a/app/assets/javascripts/groups/components/group_name_and_path.vue b/app/assets/javascripts/groups/components/group_name_and_path.vue index 1f9fc68a612..8d193310a98 100644 --- a/app/assets/javascripts/groups/components/group_name_and_path.vue +++ b/app/assets/javascripts/groups/components/group_name_and_path.vue @@ -56,7 +56,7 @@ export default { 'An error occurred while checking group path. Please refresh and try again.', ), changingUrlWarningMessage: s__('Groups|Changing group URL can have unintended side effects.'), - learnMore: s__('Groups|Learn more'), + learnMore: __('Learn more'), }, inputSize: { md: 'lg' }, changingGroupPathHelpPagePath: helpPagePath('user/group/manage', { diff --git a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue index 4d936428ea6..14fe88b8f61 100644 --- a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue +++ b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue @@ -29,6 +29,7 @@ import { getSortOptions, isSortKey, } from '~/issues/list/utils'; +import { fetchPolicies } from '~/lib/graphql'; import axios from '~/lib/utils/axios_utils'; import { scrollUp } from '~/lib/utils/scroll_utils'; import { getParameterByName } from '~/lib/utils/url_utility'; @@ -126,6 +127,10 @@ export default { update(data) { return data.issues.nodes ?? []; }, + fetchPolicy: fetchPolicies.CACHE_AND_NETWORK, + // We need this for handling loading state when using frontend cache + // See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106004#note_1217325202 for details + notifyOnNetworkStatusChange: true, result({ data }) { this.pageInfo = data?.issues.pageInfo ?? {}; }, @@ -183,6 +188,17 @@ export default { hasSearch() { return Boolean(this.searchQuery || Object.keys(this.urlFilterParams).length); }, + // due to the issues with cache-and-network, we need this hack to check if there is any data for the query in the cache. + // if we have cached data, we disregard the loading state + isLoading() { + return ( + this.$apollo.queries.issues.loading && + !this.$apollo.provider.clients.defaultClient.readQuery({ + query: getIssuesQuery, + variables: this.queryVariables, + }) + ); + }, queryVariables() { return { hideUsers: this.isPublicVisibilityRestricted && !this.isSignedIn, @@ -446,7 +462,7 @@ export default { :initial-filter-value="filterTokens" :initial-sort-by="sortKey" :issuables="renderedIssues" - :issuables-loading="$apollo.queries.issues.loading" + :issuables-loading="isLoading" namespace="dashboard" recent-searches-storage-key="issues" :search-input-placeholder="$options.i18n.searchPlaceholder" diff --git a/app/assets/javascripts/issues/dashboard/index.js b/app/assets/javascripts/issues/dashboard/index.js index 005ab5ce3b0..999f07781b2 100644 --- a/app/assets/javascripts/issues/dashboard/index.js +++ b/app/assets/javascripts/issues/dashboard/index.js @@ -1,10 +1,10 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; -import createDefaultClient from '~/lib/graphql'; +import { gqlClient } from '~/issues/list/graphql'; import { parseBoolean } from '~/lib/utils/common_utils'; import IssuesDashboardApp from './components/issues_dashboard_app.vue'; -export function mountIssuesDashboardApp() { +export async function mountIssuesDashboardApp() { const el = document.querySelector('.js-issues-dashboard'); if (!el) { @@ -34,7 +34,7 @@ export function mountIssuesDashboardApp() { el, name: 'IssuesDashboardRoot', apolloProvider: new VueApollo({ - defaultClient: createDefaultClient(), + defaultClient: await gqlClient(), }), provide: { autocompleteAwardEmojisPath, diff --git a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql index 5625e6afad3..5c331fe95e2 100644 --- a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql +++ b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql @@ -1,5 +1,5 @@ #import "~/graphql_shared/fragments/page_info.fragment.graphql" -#import "./issue.fragment.graphql" +#import "~/issues/list/queries/issue.fragment.graphql" query getDashboardIssues( $hideUsers: Boolean = false @@ -44,8 +44,9 @@ query getDashboardIssues( before: $beforeCursor first: $firstPageSize last: $lastPageSize - ) { + ) @persist { nodes { + __persist ...IssueFragment reference(full: true) } diff --git a/app/assets/javascripts/issues/dashboard/queries/issue.fragment.graphql b/app/assets/javascripts/issues/dashboard/queries/issue.fragment.graphql deleted file mode 100644 index 040763f2ba4..00000000000 --- a/app/assets/javascripts/issues/dashboard/queries/issue.fragment.graphql +++ /dev/null @@ -1,56 +0,0 @@ -fragment IssueFragment on Issue { - id - iid - confidential - createdAt - downvotes - dueDate - hidden - humanTimeEstimate - mergeRequestsCount - moved - state - title - updatedAt - closedAt - upvotes - userDiscussionsCount @include(if: $isSignedIn) - webPath - webUrl - type - assignees @skip(if: $hideUsers) { - nodes { - id - avatarUrl - name - username - webUrl - } - } - author @skip(if: $hideUsers) { - id - avatarUrl - name - username - webUrl - } - labels { - nodes { - id - color - title - description - } - } - milestone { - id - dueDate - startDate - webPath - title - } - taskCompletionStatus { - completedCount - count - } -} diff --git a/app/assets/javascripts/lib/apollo/persistence_mapper.js b/app/assets/javascripts/lib/apollo/persistence_mapper.js index 8fc7c69c79d..f8ae180107c 100644 --- a/app/assets/javascripts/lib/apollo/persistence_mapper.js +++ b/app/assets/javascripts/lib/apollo/persistence_mapper.js @@ -32,7 +32,9 @@ export const persistenceMapper = async (data) => { persistEntities.push(...entities); } else { const entity = rootQuery[key].__ref; - persistEntities.push(entity); + if (entity) { + persistEntities.push(entity); + } } } diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index d70b2e57a95..188a8540a58 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -12,6 +12,10 @@ class DashboardController < Dashboard::ApplicationController before_action :set_show_full_reference, only: [:issues, :merge_requests] before_action :check_filters_presence!, only: [:issues, :merge_requests] + before_action only: :issues do + push_frontend_feature_flag(:frontend_caching) + end + before_action only: :merge_requests do push_frontend_feature_flag(:mr_approved_filter, type: :ops) end diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index b5b023a4d64..2828d17c36f 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -19,10 +19,6 @@ class Projects::ArtifactsController < Projects::ApplicationController before_action :validate_artifacts!, except: [:index, :download, :raw, :destroy] before_action :entry, only: [:external_file, :file] - before_action only: :index do - push_frontend_feature_flag(:ci_job_artifact_bulk_destroy, @project) - end - MAX_PER_PAGE = 20 feature_category :build_artifacts diff --git a/app/graphql/mutations/ci/job_artifact/bulk_destroy.rb b/app/graphql/mutations/ci/job_artifact/bulk_destroy.rb index 53036496de4..1ef59fbeba4 100644 --- a/app/graphql/mutations/ci/job_artifact/bulk_destroy.rb +++ b/app/graphql/mutations/ci/job_artifact/bulk_destroy.rb @@ -38,11 +38,6 @@ module Mutations project = authorized_find!(id: project_id) - if Feature.disabled?(:ci_job_artifact_bulk_destroy, project) - raise Gitlab::Graphql::Errors::ResourceNotAvailable, - '`ci_job_artifact_bulk_destroy` feature flag is disabled.' - end - raise Gitlab::Graphql::Errors::ArgumentError, 'IDs array of job artifacts can not be empty' if ids.empty? result = ::Ci::JobArtifacts::BulkDeleteByProjectService.new( diff --git a/app/models/user.rb b/app/models/user.rb index 9516d162066..03d2b5d19ba 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2408,9 +2408,10 @@ class User < ApplicationRecord def authorized_groups_without_shared_membership Group.from_union( [ - groups.select(Namespace.default_select_columns), - authorized_projects.joins(:namespace).select(Namespace.default_select_columns) - ]) + groups, + Group.id_in(authorized_projects.select(:namespace_id)) + ] + ) end def authorized_groups_with_shared_membership diff --git a/app/services/packages/cleanup/execute_policy_service.rb b/app/services/packages/cleanup/execute_policy_service.rb index b432f6d0acb..891866bce5f 100644 --- a/app/services/packages/cleanup/execute_policy_service.rb +++ b/app/services/packages/cleanup/execute_policy_service.rb @@ -79,10 +79,9 @@ module Packages end def batch_deadline - strong_memoize(:batch_deadline) do - MAX_EXECUTION_TIME.from_now - end + MAX_EXECUTION_TIME.from_now end + strong_memoize_attr :batch_deadline def response_success(timeout:) ServiceResponse.success( diff --git a/app/services/packages/cleanup/update_policy_service.rb b/app/services/packages/cleanup/update_policy_service.rb index 6744accc007..911a060a18f 100644 --- a/app/services/packages/cleanup/update_policy_service.rb +++ b/app/services/packages/cleanup/update_policy_service.rb @@ -18,10 +18,9 @@ module Packages private def policy - strong_memoize(:policy) do - project.packages_cleanup_policy - end + project.packages_cleanup_policy end + strong_memoize_attr :policy def allowed? can?(current_user, :admin_package, project) diff --git a/app/services/packages/composer/create_package_service.rb b/app/services/packages/composer/create_package_service.rb index 0f5429f667e..ae5933fad7c 100644 --- a/app/services/packages/composer/create_package_service.rb +++ b/app/services/packages/composer/create_package_service.rb @@ -27,10 +27,9 @@ module Packages end def composer_json - strong_memoize(:composer_json) do - ::Packages::Composer::ComposerJsonService.new(project, target).execute - end + ::Packages::Composer::ComposerJsonService.new(project, target).execute end + strong_memoize_attr :composer_json def package_name composer_json['name'] diff --git a/app/services/packages/debian/extract_changes_metadata_service.rb b/app/services/packages/debian/extract_changes_metadata_service.rb index fdca8c88fdc..5f06f46de58 100644 --- a/app/services/packages/debian/extract_changes_metadata_service.rb +++ b/app/services/packages/debian/extract_changes_metadata_service.rb @@ -26,10 +26,9 @@ module Packages private def metadata - strong_memoize(:metadata) do - ::Packages::Debian::ExtractMetadataService.new(@package_file).execute - end + ::Packages::Debian::ExtractMetadataService.new(@package_file).execute end + strong_memoize_attr :metadata def file_type metadata[:file_type] @@ -40,20 +39,19 @@ module Packages end def files - strong_memoize(:files) do - raise ExtractionError, "is not a changes file" unless file_type == :changes - raise ExtractionError, "Files field is missing" if fields['Files'].blank? - raise ExtractionError, "Checksums-Sha1 field is missing" if fields['Checksums-Sha1'].blank? - raise ExtractionError, "Checksums-Sha256 field is missing" if fields['Checksums-Sha256'].blank? - - init_entries_from_files - entries_from_checksums_sha1 - entries_from_checksums_sha256 - entries_from_package_files - - @entries - end + raise ExtractionError, "is not a changes file" unless file_type == :changes + raise ExtractionError, "Files field is missing" if fields['Files'].blank? + raise ExtractionError, "Checksums-Sha1 field is missing" if fields['Checksums-Sha1'].blank? + raise ExtractionError, "Checksums-Sha256 field is missing" if fields['Checksums-Sha256'].blank? + + init_entries_from_files + entries_from_checksums_sha1 + entries_from_checksums_sha256 + entries_from_package_files + + @entries end + strong_memoize_attr :files def init_entries_from_files each_lines_for('Files') do |line| diff --git a/app/services/packages/debian/generate_distribution_key_service.rb b/app/services/packages/debian/generate_distribution_key_service.rb index 917965da58e..37e25c2db47 100644 --- a/app/services/packages/debian/generate_distribution_key_service.rb +++ b/app/services/packages/debian/generate_distribution_key_service.rb @@ -43,10 +43,9 @@ module Packages attr_reader :params def passphrase - strong_memoize(:passphrase) do - params[:passphrase] || ::User.random_password - end + params[:passphrase] || ::User.random_password end + strong_memoize_attr :passphrase def pinentry_script_content escaped_passphrase = Shellwords.escape(passphrase) diff --git a/app/services/packages/debian/generate_distribution_service.rb b/app/services/packages/debian/generate_distribution_service.rb index d69f6eb1511..9feb860ae87 100644 --- a/app/services/packages/debian/generate_distribution_service.rb +++ b/app/services/packages/debian/generate_distribution_service.rb @@ -213,10 +213,9 @@ module Packages end def release_content - strong_memoize(:release_content) do - release_header + release_sums - end + release_header + release_sums end + strong_memoize_attr :release_content def release_header [ @@ -235,10 +234,9 @@ module Packages end def release_date - strong_memoize(:release_date) do - Time.now.utc - end + Time.now.utc end + strong_memoize_attr :release_date def release_sums # NB: MD5Sum was removed for FIPS compliance diff --git a/app/services/packages/debian/process_changes_service.rb b/app/services/packages/debian/process_changes_service.rb index 129f2e5c9bc..abd631dbc70 100644 --- a/app/services/packages/debian/process_changes_service.rb +++ b/app/services/packages/debian/process_changes_service.rb @@ -76,10 +76,9 @@ module Packages end def metadata - strong_memoize(:metadata) do - ::Packages::Debian::ExtractChangesMetadataService.new(package_file).execute - end + ::Packages::Debian::ExtractChangesMetadataService.new(package_file).execute end + strong_memoize_attr :metadata def files metadata[:files] @@ -90,16 +89,15 @@ module Packages end def package - strong_memoize(:package) do - params = { - 'name': metadata[:fields]['Source'], - 'version': metadata[:fields]['Version'], - 'distribution_name': metadata[:fields]['Distribution'] - } - response = Packages::Debian::FindOrCreatePackageService.new(project, creator, params).execute - response.payload[:package] - end + params = { + 'name': metadata[:fields]['Source'], + 'version': metadata[:fields]['Version'], + 'distribution_name': metadata[:fields]['Distribution'] + } + response = Packages::Debian::FindOrCreatePackageService.new(project, creator, params).execute + response.payload[:package] end + strong_memoize_attr :package # used by ExclusiveLeaseGuard def lease_key diff --git a/app/services/packages/helm/process_file_service.rb b/app/services/packages/helm/process_file_service.rb index f53c63d2b01..219f3d8c781 100644 --- a/app/services/packages/helm/process_file_service.rb +++ b/app/services/packages/helm/process_file_service.rb @@ -57,28 +57,25 @@ module Packages end def temp_package - strong_memoize(:temp_package) do - package_file.package - end + package_file.package end + strong_memoize_attr :temp_package def package - strong_memoize(:package) do - project_packages = package_file.package.project.packages - package = project_packages.with_package_type(:helm) - .with_name(metadata['name']) - .with_version(metadata['version']) - .not_pending_destruction - .last - package || temp_package - end + project_packages = package_file.package.project.packages + package = project_packages.with_package_type(:helm) + .with_name(metadata['name']) + .with_version(metadata['version']) + .not_pending_destruction + .last + package || temp_package end + strong_memoize_attr :package def metadata - strong_memoize(:metadata) do - ::Packages::Helm::ExtractFileMetadataService.new(package_file).execute - end + ::Packages::Helm::ExtractFileMetadataService.new(package_file).execute end + strong_memoize_attr :metadata def file_name "#{metadata['name']}-#{metadata['version']}.tgz" diff --git a/app/services/packages/maven/metadata/base_create_xml_service.rb b/app/services/packages/maven/metadata/base_create_xml_service.rb index 3b0d93e1dfb..d67d5a21a91 100644 --- a/app/services/packages/maven/metadata/base_create_xml_service.rb +++ b/app/services/packages/maven/metadata/base_create_xml_service.rb @@ -19,12 +19,11 @@ module Packages attr_reader :logger def xml_doc - strong_memoize(:xml_doc) do - Nokogiri::XML(@metadata_content) do |config| - config.default_xml.noblanks - end + Nokogiri::XML(@metadata_content) do |config| + config.default_xml.noblanks end end + strong_memoize_attr :xml_doc def xml_node(name, content) xml_doc.create_element(name).tap { |e| e.content = content } diff --git a/app/services/packages/maven/metadata/create_plugins_xml_service.rb b/app/services/packages/maven/metadata/create_plugins_xml_service.rb index 707a8c577ba..e99a72bc0ab 100644 --- a/app/services/packages/maven/metadata/create_plugins_xml_service.rb +++ b/app/services/packages/maven/metadata/create_plugins_xml_service.rb @@ -40,37 +40,34 @@ module Packages end def plugins_xml_node - strong_memoize(:plugins_xml_node) do - xml_doc.xpath(XPATH_PLUGINS) + xml_doc.xpath(XPATH_PLUGINS) .first - end end + strong_memoize_attr :plugins_xml_node def plugin_artifact_ids_from_xml - strong_memoize(:plugin_artifact_ids_from_xml) do - plugins_xml_node.xpath(XPATH_PLUGIN_ARTIFACT_ID) + plugins_xml_node.xpath(XPATH_PLUGIN_ARTIFACT_ID) .map(&:content) - end end + strong_memoize_attr :plugin_artifact_ids_from_xml def plugin_artifact_ids_from_database - strong_memoize(:plugin_artifact_ids_from_database) do - package_names = plugin_artifact_ids_from_xml.map do |artifact_id| - "#{@package.name}/#{artifact_id}" - end - - packages = @package.project.packages - .maven - .displayable - .with_name(package_names) - .has_version - - ::Packages::Maven::Metadatum.for_package_ids(packages.select(:id)) - .order_created - .pluck_app_name - .uniq + package_names = plugin_artifact_ids_from_xml.map do |artifact_id| + "#{@package.name}/#{artifact_id}" end + + packages = @package.project.packages + .maven + .displayable + .with_name(package_names) + .has_version + + ::Packages::Maven::Metadatum.for_package_ids(packages.select(:id)) + .order_created + .pluck_app_name + .uniq end + strong_memoize_attr :plugin_artifact_ids_from_database def plugin_node_for(artifact_id) xml_doc.create_element('plugin').tap do |plugin_node| diff --git a/app/services/packages/maven/metadata/create_versions_xml_service.rb b/app/services/packages/maven/metadata/create_versions_xml_service.rb index c2ac7fea703..966540bcba2 100644 --- a/app/services/packages/maven/metadata/create_versions_xml_service.rb +++ b/app/services/packages/maven/metadata/create_versions_xml_service.rb @@ -91,49 +91,43 @@ module Packages end def versioning_xml_node - strong_memoize(:versioning_xml_node) do - xml_doc.xpath(XPATH_VERSIONING).first - end + xml_doc.xpath(XPATH_VERSIONING).first end + strong_memoize_attr :versioning_xml_node def versions_xml_node - strong_memoize(:versions_xml_node) do - versioning_xml_node&.xpath(XPATH_VERSIONS) + versioning_xml_node&.xpath(XPATH_VERSIONS) &.first - end end + strong_memoize_attr :versions_xml_node def version_xml_nodes versions_xml_node&.xpath(XPATH_VERSION) end def latest_xml_node - strong_memoize(:latest_xml_node) do - versioning_xml_node&.xpath(XPATH_LATEST) + versioning_xml_node&.xpath(XPATH_LATEST) &.first - end end + strong_memoize_attr :latest_xml_node def release_xml_node - strong_memoize(:release_xml_node) do - versioning_xml_node&.xpath(XPATH_RELEASE) + versioning_xml_node&.xpath(XPATH_RELEASE) &.first - end end + strong_memoize_attr :release_xml_node def last_updated_xml_node - strong_memoize(:last_updated_xml_mode) do - versioning_xml_node.xpath(XPATH_LAST_UPDATED) + versioning_xml_node.xpath(XPATH_LAST_UPDATED) .first - end end + strong_memoize_attr :last_updated_xml_node def versions_from_xml - strong_memoize(:versions_from_xml) do - versions_xml_node.xpath(XPATH_VERSION) + versions_xml_node.xpath(XPATH_VERSION) .map(&:text) - end end + strong_memoize_attr :versions_from_xml def latest_from_xml latest_xml_node&.text @@ -144,27 +138,25 @@ module Packages end def versions_from_database - strong_memoize(:versions_from_database) do - @package.project.packages + @package.project.packages .maven .displayable .with_name(@package.name) .has_version .order_created .pluck_versions - end end + strong_memoize_attr :versions_from_database def latest_from_database versions_from_database.last end def release_from_database - strong_memoize(:release_from_database) do - non_snapshot_versions_from_database = versions_from_database.reject { |v| v.ends_with?('SNAPSHOT') } - non_snapshot_versions_from_database.last - end + non_snapshot_versions_from_database = versions_from_database.reject { |v| v.ends_with?('SNAPSHOT') } + non_snapshot_versions_from_database.last end + strong_memoize_attr :release_from_database def log_malformed_content(reason) logger.warn( diff --git a/app/services/packages/maven/metadata/sync_service.rb b/app/services/packages/maven/metadata/sync_service.rb index dacf6750412..14196f090dd 100644 --- a/app/services/packages/maven/metadata/sync_service.rb +++ b/app/services/packages/maven/metadata/sync_service.rb @@ -70,25 +70,22 @@ module Packages end def metadata_package_file_for_versions - strong_memoize(:metadata_file_for_versions) do - metadata_package_file_for(versionless_package_for_versions) - end + metadata_package_file_for(versionless_package_for_versions) end + strong_memoize_attr :metadata_package_file_for_versions def versionless_package_for_versions - strong_memoize(:versionless_package_for_versions) do - versionless_package_named(package_name) - end + versionless_package_named(package_name) end + strong_memoize_attr :versionless_package_for_versions def metadata_package_file_for_plugins - strong_memoize(:metadata_package_file_for_plugins) do - pkg_name = package_name_for_plugins - next unless pkg_name + pkg_name = package_name_for_plugins + return unless pkg_name - metadata_package_file_for(versionless_package_named(package_name_for_plugins)) - end + metadata_package_file_for(versionless_package_named(package_name_for_plugins)) end + strong_memoize_attr :metadata_package_file_for_plugins def metadata_package_file_for(package) return unless package diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb index c71ae060dd9..2c578760cc5 100644 --- a/app/services/packages/npm/create_package_service.rb +++ b/app/services/packages/npm/create_package_service.rb @@ -61,10 +61,9 @@ module Packages end def version - strong_memoize(:version) do - params[:versions].each_key.first - end + params[:versions].each_key.first end + strong_memoize_attr :version def version_data params[:versions][version] @@ -79,30 +78,27 @@ module Packages end def package_file_name - strong_memoize(:package_file_name) do - "#{name}-#{version}.tgz" - end + "#{name}-#{version}.tgz" end + strong_memoize_attr :package_file_name def attachment - strong_memoize(:attachment) do - params['_attachments'][package_file_name] - end + params['_attachments'][package_file_name] end + strong_memoize_attr :attachment # TODO (technical debt): Extract the package size calculation to its own component and unit test it separately. def calculated_package_file_size - strong_memoize(:calculated_package_file_size) do - # This calculation is based on: - # 1. 4 chars in a Base64 encoded string are 3 bytes in the original string. Meaning 1 char is 0.75 bytes. - # 2. The encoded string may have 1 or 2 extra '=' chars used for padding. Each padding char means 1 byte less in the original string. - # Reference: - # - https://blog.aaronlenoir.com/2017/11/10/get-original-length-from-base-64-string/ - # - https://en.wikipedia.org/wiki/Base64#Decoding_Base64_with_padding - encoded_data = attachment['data'] - ((encoded_data.length * 0.75) - encoded_data[-2..].count('=')).to_i - end + # This calculation is based on: + # 1. 4 chars in a Base64 encoded string are 3 bytes in the original string. Meaning 1 char is 0.75 bytes. + # 2. The encoded string may have 1 or 2 extra '=' chars used for padding. Each padding char means 1 byte less in the original string. + # Reference: + # - https://blog.aaronlenoir.com/2017/11/10/get-original-length-from-base-64-string/ + # - https://en.wikipedia.org/wiki/Base64#Decoding_Base64_with_padding + encoded_data = attachment['data'] + ((encoded_data.length * 0.75) - encoded_data[-2..].count('=')).to_i end + strong_memoize_attr :calculated_package_file_size def file_params { @@ -134,29 +130,26 @@ module Packages end def field_sizes - strong_memoize(:field_sizes) do - package_json.transform_values do |value| - value.to_s.size - end + package_json.transform_values do |value| + value.to_s.size end end + strong_memoize_attr :field_sizes def filtered_field_sizes - strong_memoize(:filtered_field_sizes) do - field_sizes.select do |_, size| - size >= ::Packages::Npm::Metadatum::MIN_PACKAGE_JSON_FIELD_SIZE_FOR_ERROR_TRACKING - end + field_sizes.select do |_, size| + size >= ::Packages::Npm::Metadatum::MIN_PACKAGE_JSON_FIELD_SIZE_FOR_ERROR_TRACKING end end + strong_memoize_attr :filtered_field_sizes def largest_fields - strong_memoize(:largest_fields) do - field_sizes + field_sizes .sort_by { |a| a[1] } .reverse[0..::Packages::Npm::Metadatum::NUM_FIELDS_FOR_ERROR_TRACKING - 1] .to_h - end end + strong_memoize_attr :largest_fields def field_sizes_for_error_tracking filtered_field_sizes.empty? ? largest_fields : filtered_field_sizes diff --git a/app/services/packages/npm/create_tag_service.rb b/app/services/packages/npm/create_tag_service.rb index 82974d0ca4b..e212b37c9ba 100644 --- a/app/services/packages/npm/create_tag_service.rb +++ b/app/services/packages/npm/create_tag_service.rb @@ -23,12 +23,11 @@ module Packages private def existing_tag - strong_memoize(:existing_tag) do - Packages::TagsFinder + Packages::TagsFinder .new(package.project, package.name, package_type: package.package_type) .find_by_name(tag_name) - end end + strong_memoize_attr :existing_tag end end end diff --git a/app/services/packages/nuget/metadata_extraction_service.rb b/app/services/packages/nuget/metadata_extraction_service.rb index 3b92d977c79..5c60a2912ae 100644 --- a/app/services/packages/nuget/metadata_extraction_service.rb +++ b/app/services/packages/nuget/metadata_extraction_service.rb @@ -39,10 +39,9 @@ module Packages private def package_file - strong_memoize(:package_file) do - ::Packages::PackageFile.find_by_id(@package_file_id) - end + ::Packages::PackageFile.find_by_id(@package_file_id) end + strong_memoize_attr :package_file def valid_package_file? package_file && diff --git a/app/services/packages/nuget/search_service.rb b/app/services/packages/nuget/search_service.rb index fea424b3aa8..7d1585f8903 100644 --- a/app/services/packages/nuget/search_service.rb +++ b/app/services/packages/nuget/search_service.rb @@ -89,17 +89,16 @@ module Packages end def base_matching_package_names - strong_memoize(:base_matching_package_names) do - # rubocop: disable CodeReuse/ActiveRecord - pkgs = nuget_packages.order_name + # rubocop: disable CodeReuse/ActiveRecord + pkgs = nuget_packages.order_name .select_distinct_name .where(project_id: project_ids) - pkgs = pkgs.without_version_like(PRE_RELEASE_VERSION_MATCHING_TERM) unless include_prerelease_versions? - pkgs = pkgs.search_by_name(@search_term) if @search_term.present? - pkgs - # rubocop: enable CodeReuse/ActiveRecord - end + pkgs = pkgs.without_version_like(PRE_RELEASE_VERSION_MATCHING_TERM) unless include_prerelease_versions? + pkgs = pkgs.search_by_name(@search_term) if @search_term.present? + pkgs + # rubocop: enable CodeReuse/ActiveRecord end + strong_memoize_attr :base_matching_package_names def nuget_packages Packages::Package.nuget @@ -111,11 +110,10 @@ module Packages def project_ids_cte return unless use_project_ids_cte? - strong_memoize(:project_ids_cte) do - query = projects_visible_to_user(@current_user, within_group: @project_or_group) - Gitlab::SQL::CTE.new(:project_ids, query.select(:id)) - end + query = projects_visible_to_user(@current_user, within_group: @project_or_group) + Gitlab::SQL::CTE.new(:project_ids, query.select(:id)) end + strong_memoize_attr :project_ids_cte def project_ids return @project_or_group.id if project? diff --git a/app/services/packages/pypi/create_package_service.rb b/app/services/packages/pypi/create_package_service.rb index b464ce4504a..087a8e42a66 100644 --- a/app/services/packages/pypi/create_package_service.rb +++ b/app/services/packages/pypi/create_package_service.rb @@ -29,10 +29,9 @@ module Packages private def created_package - strong_memoize(:created_package) do - find_or_create_package!(:pypi) - end + find_or_create_package!(:pypi) end + strong_memoize_attr :created_package def file_params { diff --git a/app/services/packages/rpm/parse_package_service.rb b/app/services/packages/rpm/parse_package_service.rb index d2751c77c5b..3995eedef53 100644 --- a/app/services/packages/rpm/parse_package_service.rb +++ b/app/services/packages/rpm/parse_package_service.rb @@ -43,10 +43,9 @@ module Packages end def package_tags - strong_memoize(:package_tags) do - rpm.tags - end + rpm.tags end + strong_memoize_attr :package_tags def extract_static_attributes STATIC_ATTRIBUTES.index_with do |attribute| diff --git a/app/services/packages/rubygems/dependency_resolver_service.rb b/app/services/packages/rubygems/dependency_resolver_service.rb index 839a7683632..214a4adc47f 100644 --- a/app/services/packages/rubygems/dependency_resolver_service.rb +++ b/app/services/packages/rubygems/dependency_resolver_service.rb @@ -33,10 +33,9 @@ module Packages private def packages - strong_memoize(:packages) do - project.packages.with_name(gem_name) - end + project.packages.with_name(gem_name) end + strong_memoize_attr :packages def gem_name params[:gem_name] diff --git a/app/services/packages/rubygems/process_gem_service.rb b/app/services/packages/rubygems/process_gem_service.rb index c771af28f73..ca4aaa8fdde 100644 --- a/app/services/packages/rubygems/process_gem_service.rb +++ b/app/services/packages/rubygems/process_gem_service.rb @@ -64,10 +64,9 @@ module Packages end def gemspec - strong_memoize(:gemspec) do - gem.spec - end + gem.spec end + strong_memoize_attr :gemspec def success ServiceResponse.success(payload: { package: package }) @@ -78,24 +77,21 @@ module Packages end def temp_package - strong_memoize(:temp_package) do - package_file.package - end + package_file.package end + strong_memoize_attr :temp_package def package - strong_memoize(:package) do - # if package with name/version already exists, use that package - package = temp_package.project + package = temp_package.project .packages .rubygems .with_name(gemspec.name) .with_version(gemspec.version.to_s) .not_pending_destruction .last - package || temp_package - end + package || temp_package end + strong_memoize_attr :package def gem # use_file will set an exclusive lease on the file for as long as diff --git a/app/services/packages/terraform_module/create_package_service.rb b/app/services/packages/terraform_module/create_package_service.rb index 3afecc6c1ca..9df722db529 100644 --- a/app/services/packages/terraform_module/create_package_service.rb +++ b/app/services/packages/terraform_module/create_package_service.rb @@ -43,16 +43,14 @@ module Packages end def name - strong_memoize(:name) do - "#{params[:module_name]}/#{params[:module_system]}" - end + "#{params[:module_name]}/#{params[:module_system]}" end + strong_memoize_attr :name def file_name - strong_memoize(:file_name) do - "#{params[:module_name]}-#{params[:module_system]}-#{params[:module_version]}.tgz" - end + "#{params[:module_name]}-#{params[:module_system]}-#{params[:module_version]}.tgz" end + strong_memoize_attr :file_name def file_params { diff --git a/app/services/packages/update_tags_service.rb b/app/services/packages/update_tags_service.rb index f29c54dacb9..cf1acc6ee19 100644 --- a/app/services/packages/update_tags_service.rb +++ b/app/services/packages/update_tags_service.rb @@ -21,10 +21,9 @@ module Packages private def existing_tags - strong_memoize(:existing_tags) do - @package.tag_names - end + @package.tag_names end + strong_memoize_attr :existing_tags def rows(tags) now = Time.zone.now diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 91a54f15305..fec5d2d5ff5 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -52,7 +52,7 @@ %p = s_('Profiles|Changing your username can have unintended side effects.') = succeed '.' do - = link_to s_('Profiles|Learn more'), help_page_path('user/profile/index', anchor: 'change-your-username'), target: '_blank', rel: 'noopener noreferrer' + = link_to _('Learn more'), help_page_path('user/profile/index', anchor: 'change-your-username'), target: '_blank', rel: 'noopener noreferrer' .col-lg-8 - data = { initial_username: current_user.username, root_url: root_url, action_url: update_username_profile_path(format: :json) } #update-username{ data: data } diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml index f4b6c3c3a50..216aaad443f 100644 --- a/app/views/shared/runners/_form.html.haml +++ b/app/views/shared/runners/_form.html.haml @@ -42,12 +42,12 @@ - if local_assigns[:in_gitlab_com_admin_context] .form-group.row = label_tag :public_projects_minutes_cost_factor, class: 'col-form-label col-sm-2' do - = _('Public projects Minutes cost factor') + = _('Public projects compute cost factor') .col-sm-10 = f.text_field :public_projects_minutes_cost_factor, class: 'form-control' .form-group.row = label_tag :private_projects_minutes_cost_factor, class: 'col-form-label col-sm-2' do - = _('Private projects Minutes cost factor') + = _('Private projects compute cost factor') .col-sm-10 = f.text_field :private_projects_minutes_cost_factor, class: 'form-control' .form-actions diff --git a/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb b/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb index e7eee0915d5..b2dfded0280 100644 --- a/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb +++ b/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb @@ -16,6 +16,12 @@ module Gitlab # project - An instance of Project. def import(client, project) info(project.id, message: "starting importer", importer: 'Importer::PullRequestsImporter') + + # If a user creates a new merge request while the import is in progress, GitLab can assign an IID + # to this merge request that already exists for a GitHub Pull Request. + # The workaround is to allocate IIDs before starting the importer. + allocate_merge_requests_internal_id!(project, client) + waiter = Importer::PullRequestsImporter .new(project, client) .execute @@ -41,6 +47,17 @@ module Gitlab private + def allocate_merge_requests_internal_id!(project, client) + return if InternalId.exists?(project: project, usage: :merge_requests) # rubocop: disable CodeReuse/ActiveRecord + + options = { state: 'all', sort: 'number', direction: 'desc', per_page: '1' } + last_github_pull_request = client.each_object(:pulls, project.import_source, options).first + + return unless last_github_pull_request + + MergeRequest.track_target_project_iid!(project, last_github_pull_request[:number]) + end + def abort_on_failure true end |