From baed745d21710f1d78ece03558873acd6fd7d358 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 28 Feb 2023 15:11:48 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- Gemfile | 2 +- Gemfile.checksum | 17 +- Gemfile.lock | 4 +- .../boards/components/board_content_sidebar.vue | 6 +- app/assets/javascripts/boards/constants.js | 12 +- app/assets/javascripts/boards/index.js | 7 +- app/assets/javascripts/boards/stores/actions.js | 23 +-- .../show/components/incidents/incident_tabs.vue | 16 +- .../issues/show/components/incidents/router.js | 20 ++ app/assets/javascripts/issues/show/index.js | 5 + app/controllers/concerns/renders_notes.rb | 4 +- .../profiles/notifications_controller.rb | 5 +- app/controllers/projects/branches_controller.rb | 2 +- app/finders/autocomplete/users_finder.rb | 2 +- .../ci/pipeline_job_artifacts_resolver.rb | 2 +- app/graphql/types/board_list_type.rb | 2 +- app/helpers/issuables_helper.rb | 4 +- app/models/ci/build.rb | 8 +- app/models/ci/build_metadata.rb | 4 +- app/models/ci/runner_machine.rb | 4 +- app/models/ci/runner_machine_build.rb | 23 +++ app/models/concerns/ci/partitionable.rb | 1 + app/models/concerns/partitioned_table.rb | 3 +- app/models/concerns/routable.rb | 57 +++-- app/models/draft_note.rb | 2 +- app/models/group.rb | 6 +- app/models/members_preloader.rb | 17 +- app/models/preloaders/commit_status_preloader.rb | 7 +- app/models/preloaders/labels_preloader.rb | 17 +- app/models/preloaders/project_policy_preloader.rb | 5 +- .../preloaders/project_root_ancestor_preloader.rb | 2 +- app/models/project.rb | 6 +- app/models/resource_label_event.rb | 5 +- app/presenters/README.md | 12 +- app/presenters/ci/build_runner_presenter.rb | 2 +- app/services/ci/register_job_service.rb | 2 +- .../issues/referenced_merge_requests_service.rb | 7 +- app/workers/all_queues.yml | 4 +- app/workers/group_destroy_worker.rb | 5 +- app/workers/project_destroy_worker.rb | 5 +- config/gitlab_loose_foreign_keys.yml | 4 + config/initializers/active_record_preloader.rb | 11 + config/initializers/postgres_partitioning.rb | 3 +- .../index_inconsistencies_metric.json | 19 ++ ...20230203164341_index_inconsistencies_metric.yml | 25 +++ config/routes/issues.rb | 9 +- db/docs/p_ci_runner_machine_builds.yml | 4 +- ...hanged_in_to_vulnerability_state_transitions.rb | 11 + ..._over_limit_check_at_asc_order_synchronously.rb | 17 ++ ...peline_fk_to_vulnerability_state_transitions.rb | 15 ++ ...ild_trace_metadata_partition_id_and_build_id.rb | 15 ++ ...i_builds_ci_build_trace_metadata_on_build_id.rb | 35 ++++ db/schema_migrations/20230217232554 | 1 + db/schema_migrations/20230219191034 | 1 + db/schema_migrations/20230227151608 | 1 + db/schema_migrations/20230227151609 | 1 + db/schema_migrations/20230228092612 | 1 + db/structure.sql | 10 +- doc/architecture/blueprints/runner_tokens/index.md | 14 +- .../merge_request_concepts/performance.md | 2 +- doc/integration/partner_marketplace.md | 2 +- doc/operations/quickstart-guide.md | 229 --------------------- doc/user/group/import/index.md | 20 +- doc/user/profile/personal_access_tokens.md | 2 +- lib/api/entities/project.rb | 2 +- .../cycle_analytics/aggregated/records_fetcher.rb | 8 +- .../analytics/cycle_analytics/records_fetcher.rb | 8 +- lib/gitlab/data_builder/pipeline.rb | 7 +- .../partitioning/ci_sliding_list_strategy.rb | 27 +++ .../schema_validation/validators/base_validator.rb | 10 +- .../validators/different_definition_indexes.rb | 22 ++ .../schema_validation/validators/extra_indexes.rb | 2 +- .../validators/missing_indexes.rb | 2 +- .../schema_validation/validators/wrong_indexes.rb | 22 -- .../index_inconsistencies_metric.rb | 46 +++++ lib/tasks/gitlab/tw/codeowners.rake | 1 - locale/gitlab.pot | 3 + .../projects/branches_controller_spec.rb | 1 + spec/db/schema_spec.rb | 2 +- spec/factories/ci/runner_machine_builds.rb | 8 + .../incidents/incident_timeline_events_spec.rb | 3 +- .../incidents/user_views_alert_details_spec.rb | 34 +++ .../boards/components/board_top_bar_spec.js | 10 +- .../boards/components/boards_selector_spec.js | 10 +- spec/frontend/boards/stores/actions_spec.js | 14 +- .../components/incidents/incident_tabs_spec.js | 42 ++++ spec/helpers/issuables_helper_spec.rb | 7 +- .../database/schema_validation/runner_spec.rb | 4 +- .../validators/base_validator_spec.rb | 2 +- .../different_definition_indexes_spec.rb | 8 + .../validators/wrong_indexes_spec.rb | 7 - spec/lib/gitlab/import_export/all_models.yml | 2 + .../index_inconsistencies_metric_spec.rb | 30 +++ spec/models/ci/build_metadata_spec.rb | 1 - spec/models/ci/build_spec.rb | 2 +- spec/models/ci/processable_spec.rb | 2 +- spec/models/ci/runner_machine_build_spec.rb | 50 +++++ spec/models/ci/runner_machine_spec.rb | 4 +- spec/models/concerns/routable_spec.rb | 11 + spec/requests/projects/issues_controller_spec.rb | 28 +-- .../incident_details_routing_shared_examples.rb | 14 +- .../database/index_validators_shared_examples.rb | 7 +- spec/workers/group_destroy_worker_spec.rb | 23 ++- spec/workers/project_destroy_worker_spec.rb | 25 ++- workhorse/go.mod | 2 +- workhorse/go.sum | 4 +- 106 files changed, 806 insertions(+), 500 deletions(-) create mode 100644 app/assets/javascripts/issues/show/components/incidents/router.js create mode 100644 app/models/ci/runner_machine_build.rb create mode 100644 config/metrics/objects_schemas/index_inconsistencies_metric.json create mode 100644 config/metrics/settings/20230203164341_index_inconsistencies_metric.yml create mode 100644 db/migrate/20230217232554_add_state_changed_in_to_vulnerability_state_transitions.rb create mode 100644 db/migrate/20230228092612_add_index_next_over_limit_check_at_asc_order_synchronously.rb create mode 100644 db/post_migrate/20230219191034_add_pipeline_fk_to_vulnerability_state_transitions.rb create mode 100644 db/post_migrate/20230227151608_validate_fk_on_ci_build_trace_metadata_partition_id_and_build_id.rb create mode 100644 db/post_migrate/20230227151609_remove_fk_to_ci_builds_ci_build_trace_metadata_on_build_id.rb create mode 100644 db/schema_migrations/20230217232554 create mode 100644 db/schema_migrations/20230219191034 create mode 100644 db/schema_migrations/20230227151608 create mode 100644 db/schema_migrations/20230227151609 create mode 100644 db/schema_migrations/20230228092612 delete mode 100644 doc/operations/quickstart-guide.md create mode 100644 lib/gitlab/database/partitioning/ci_sliding_list_strategy.rb create mode 100644 lib/gitlab/database/schema_validation/validators/different_definition_indexes.rb delete mode 100644 lib/gitlab/database/schema_validation/validators/wrong_indexes.rb create mode 100644 lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric.rb create mode 100644 spec/factories/ci/runner_machine_builds.rb create mode 100644 spec/features/incidents/user_views_alert_details_spec.rb create mode 100644 spec/lib/gitlab/database/schema_validation/validators/different_definition_indexes_spec.rb delete mode 100644 spec/lib/gitlab/database/schema_validation/validators/wrong_indexes_spec.rb create mode 100644 spec/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric_spec.rb create mode 100644 spec/models/ci/runner_machine_build_spec.rb diff --git a/Gemfile b/Gemfile index 3bf40a6aba0..5f12365e395 100644 --- a/Gemfile +++ b/Gemfile @@ -518,7 +518,7 @@ gem 'kas-grpc', '~> 0.0.2' gem 'grpc', '~> 1.42.0' -gem 'google-protobuf', '~> 3.21', '>= 3.21.12' +gem 'google-protobuf', '~> 3.22' gem 'toml-rb', '~> 2.2.0' diff --git a/Gemfile.checksum b/Gemfile.checksum index c3dfd696b68..592d11baac2 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -232,14 +232,15 @@ {"name":"google-cloud-env","version":"1.6.0","platform":"ruby","checksum":"6179acb946975892c7908748df5722a4ebadfc8cf5bb7b0d8d933ca67183fa15"}, {"name":"google-cloud-errors","version":"1.3.0","platform":"ruby","checksum":"450b681e24c089a20721a01acc4408bb4a7b0df28c175aaab488da917480d64b"}, {"name":"google-cloud-storage","version":"1.44.0","platform":"ruby","checksum":"299a1e055c9277c8120f7c10d21d37e4d8c17c7b963350c0e0bff7e9d9a570ea"}, -{"name":"google-protobuf","version":"3.21.12","platform":"java","checksum":"35362ef8abf98ad597dffee588390b8b3b2f0f3d70261c3eed3f99e564f3289d"}, -{"name":"google-protobuf","version":"3.21.12","platform":"ruby","checksum":"4b09bb7e3168cda689efebcd3373304e124b14aabf776fbf1f0a7615259c8fb5"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x64-mingw-ucrt","checksum":"e4444119acd56bf4661b3f38dc2795abae2cd5c2ade88154d5fc405008fbdcf7"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x64-mingw32","checksum":"e6a879e1100f04506aea352d22f70a0ed77899fc64af3ff8c24a242331be923d"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x86-linux","checksum":"54bbacbca58323fab222746df30e60a55df89f699e319ce0774d5bdd637b3a54"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x86-mingw32","checksum":"979e6388dd5f3171043c5a00ac2f66b2789d7fc67b18207d1aabfa1dc27d9558"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x86_64-darwin","checksum":"d7e59bd1040e510fd67fb96d08be84a4e362641f5229bf3fd870e383b2913574"}, -{"name":"google-protobuf","version":"3.21.12","platform":"x86_64-linux","checksum":"cb6820a68c7807e12ca1e6b69689b833d675ed81435a2179d502575ed5db3de0"}, +{"name":"google-protobuf","version":"3.22.0","platform":"arm64-darwin","checksum":"e47680f8cf46d5e0bf573052047276260d785caf7b586719af407767e96e535c"}, +{"name":"google-protobuf","version":"3.22.0","platform":"java","checksum":"24e55a0665113f60af35e27dd4c1fcc9b08d16f9da7605456634e505c95890b3"}, +{"name":"google-protobuf","version":"3.22.0","platform":"ruby","checksum":"58db86f65c686ef4b9389569faa176bada384850751675f0c3736ef76cdcae90"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x64-mingw-ucrt","checksum":"43ce8f98fdfa06a81397577bb502230d545178afd592ef5e7d2daddacdda8eb6"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x64-mingw32","checksum":"8255654f5a4a7fff0d430357fa9fe2f23db16eb17ed1067b46a1aab7fd9fcbab"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x86-linux","checksum":"2794f32ecfbeec0fd7baa4a61292fa220f5aad07b656ba656ecf134b1f7e8425"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x86-mingw32","checksum":"a037a5ed2d0a1faa556466c34f7177fee1f3aee8282c2195aed804fead65c65d"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x86_64-darwin","checksum":"bff2987e4bf1a934a4555aea2020df18b557393b188c849fb9deacec9ed0f3d9"}, +{"name":"google-protobuf","version":"3.22.0","platform":"x86_64-linux","checksum":"a0ea6aa03602e9e4f11c1506a114777204aade2e04adc2051945536c35d88bfe"}, {"name":"googleapis-common-protos-types","version":"1.3.0","platform":"ruby","checksum":"c5411f3197cc3e02547ded1858303b1f830b4dc89c588c142ad6c8a231050671"}, {"name":"googleauth","version":"1.3.0","platform":"ruby","checksum":"51dd7362353cf1e90a2d01e1fb94321ae3926c776d4dc4a79db65230217ffcc2"}, {"name":"gpgme","version":"2.0.22","platform":"ruby","checksum":"7c6904952afdd0bf2c7c3ed6de98a5143f86c6b7390dbcd9d7012bddfa3ec862"}, diff --git a/Gemfile.lock b/Gemfile.lock index e6e4c005945..c8c2c775198 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -668,7 +668,7 @@ GEM google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - google-protobuf (3.21.12) + google-protobuf (3.22.0) googleapis-common-protos-types (1.3.0) google-protobuf (~> 3.14) googleauth (1.3.0) @@ -1699,7 +1699,7 @@ DEPENDENCIES google-apis-serviceusage_v1 (~> 0.28.0) google-apis-sqladmin_v1beta4 (~> 0.41.0) google-cloud-storage (~> 1.44.0) - google-protobuf (~> 3.21, >= 3.21.12) + google-protobuf (~> 3.22) gpgme (~> 2.0.22) grape (~> 1.5.2) grape-entity (~> 0.10.0) diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue index 6227f185eda..e928ed6ae0e 100644 --- a/app/assets/javascripts/boards/components/board_content_sidebar.vue +++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue @@ -6,9 +6,9 @@ import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdow import { __, sprintf } from '~/locale'; import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue'; import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue'; -import { BoardType, ISSUABLE, INCIDENT } from '~/boards/constants'; +import { ISSUABLE, INCIDENT } from '~/boards/constants'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import { TYPE_ISSUE } from '~/issues/constants'; +import { TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue'; import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue'; import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue'; @@ -98,7 +98,7 @@ export default { return this.activeBoardItem?.referencePath?.split('#')[0] || ''; }, parentType() { - return this.isGroupBoard ? BoardType.group : BoardType.project; + return this.isGroupBoard ? WORKSPACE_GROUP : WORKSPACE_PROJECT; }, createLabelTitle() { return sprintf(__('Create %{workspace} label'), { diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js index 7b7d2493ca5..948834d69e5 100644 --- a/app/assets/javascripts/boards/constants.js +++ b/app/assets/javascripts/boards/constants.js @@ -1,5 +1,5 @@ import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql'; -import { TYPE_EPIC, TYPE_ISSUE } from '~/issues/constants'; +import { TYPE_EPIC, TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import { s__, __ } from '~/locale'; import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql'; import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql'; @@ -12,11 +12,6 @@ import groupBoardQuery from './graphql/group_board.query.graphql'; import projectBoardQuery from './graphql/project_board.query.graphql'; import listIssuesQuery from './graphql/lists_issues.query.graphql'; -export const BoardType = { - project: 'project', - group: 'group', -}; - export const ListType = { assignee: 'assignee', milestone: 'milestone', @@ -56,10 +51,10 @@ export const INCIDENT = 'INCIDENT'; export const flashAnimationDuration = 2000; export const boardQuery = { - [BoardType.group]: { + [WORKSPACE_GROUP]: { query: groupBoardQuery, }, - [BoardType.project]: { + [WORKSPACE_PROJECT]: { query: projectBoardQuery, }, }; @@ -147,7 +142,6 @@ export const MilestoneIDs = { }; export default { - BoardType, ListType, }; diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index 4c6f341828c..67388284d31 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -3,9 +3,8 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import BoardApp from '~/boards/components/board_app.vue'; import '~/boards/filters/due_date_filters'; -import { BoardType } from '~/boards/constants'; import store from '~/boards/stores'; -import { TYPE_ISSUE } from '~/issues/constants'; +import { TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import { NavigationType, isLoggedIn, @@ -68,8 +67,8 @@ function mountBoardApp(el) { initialFilterParams, boardBaseUrl: el.dataset.boardBaseUrl, boardType, - isGroupBoard: boardType === BoardType.group, - isProjectBoard: boardType === BoardType.project, + isGroupBoard: boardType === WORKSPACE_GROUP, + isProjectBoard: boardType === WORKSPACE_PROJECT, currentUserId: gon.current_user_id || null, boardWeight: el.dataset.boardWeight ? parseInt(el.dataset.boardWeight, 10) : null, labelsManagePath: el.dataset.labelsManagePath, diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index c210a419771..a144054d680 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -1,7 +1,6 @@ import * as Sentry from '@sentry/browser'; import { sortBy } from 'lodash'; import { - BoardType, ListType, inactiveId, flashAnimationDuration, @@ -34,7 +33,7 @@ import totalCountAndWeightQuery from 'ee_else_ce/boards/graphql/board_lists_defe import { fetchPolicies } from '~/lib/graphql'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client'; -import { TYPE_ISSUE } from '~/issues/constants'; +import { TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { queryToObject } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; @@ -61,7 +60,7 @@ export default { return gqlClient .query({ - query: boardType === BoardType.group ? groupBoardQuery : projectBoardQuery, + query: boardType === WORKSPACE_GROUP ? groupBoardQuery : projectBoardQuery, variables, }) .then(({ data }) => { @@ -139,8 +138,8 @@ export default { boardId: fullBoardId, filters: filterParams, ...(issuableType === TYPE_ISSUE && { - isGroup: boardType === BoardType.group, - isProject: boardType === BoardType.project, + isGroup: boardType === WORKSPACE_GROUP, + isProject: boardType === WORKSPACE_PROJECT, }), }; @@ -234,8 +233,8 @@ export default { const variables = { fullPath, searchTerm, - isGroup: boardType === BoardType.group, - isProject: boardType === BoardType.project, + isGroup: boardType === WORKSPACE_GROUP, + isProject: boardType === WORKSPACE_PROJECT, }; commit(types.RECEIVE_LABELS_REQUEST); @@ -268,10 +267,10 @@ export default { }; let query; - if (boardType === BoardType.project) { + if (boardType === WORKSPACE_PROJECT) { query = projectBoardMilestonesQuery; } - if (boardType === BoardType.group) { + if (boardType === WORKSPACE_GROUP) { query = groupBoardMilestonesQuery; } @@ -431,8 +430,8 @@ export default { boardId: fullBoardId, id: listId, filters: filterParams, - isGroup: boardType === BoardType.group, - isProject: boardType === BoardType.project, + isGroup: boardType === WORKSPACE_GROUP, + isProject: boardType === WORKSPACE_PROJECT, first: DEFAULT_BOARD_LIST_ITEMS_SIZE, after: fetchNext ? state.pageInfoByListId[listId].endCursor : undefined, }; @@ -710,7 +709,7 @@ export default { ) => { const input = formatIssueInput(issueInput, boardConfig); - if (boardType === BoardType.project) { + if (boardType === WORKSPACE_PROJECT) { input.projectPath = fullPath; } diff --git a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue index 755287bf8a1..1c677c0d9e6 100644 --- a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue +++ b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue @@ -59,13 +59,16 @@ export default { data() { return { alert: null, - activeTabIndex: 0, }; }, computed: { loading() { return this.$apollo.queries.alert.loading; }, + activeTabIndex() { + const { tabId } = this.$route.params; + return tabId ? this.tabMapping.tabNamesToIndex[tabId] : 0; + }, tabMapping() { const availableTabs = [TAB_NAMES.SUMMARY]; @@ -93,20 +96,25 @@ export default { return this.activeTabIndex; }, set(index) { - this.handleTabChange(index); - this.activeTabIndex = index; + const newPath = `/${this.tabMapping.tabIndexToName[index]}`; + // Only push if the new path differs from the old path. + if (newPath !== this.$route.path) { + this.$router.push(newPath); + this.updateJsIssueWidgets(index); + } }, }, }, mounted() { this.trackPageViews(); + this.updateJsIssueWidgets(this.activeTabIndex); }, methods: { trackPageViews() { const { category, action } = trackIncidentDetailsViewsOptions; Tracking.event(category, action); }, - handleTabChange(tabIndex) { + updateJsIssueWidgets(tabIndex) { /** * TODO: Implement a solution that does not violate Vue principles in using * DOM manipulation directly (#361618) diff --git a/app/assets/javascripts/issues/show/components/incidents/router.js b/app/assets/javascripts/issues/show/components/incidents/router.js new file mode 100644 index 00000000000..01326f3b5de --- /dev/null +++ b/app/assets/javascripts/issues/show/components/incidents/router.js @@ -0,0 +1,20 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; + +Vue.use(VueRouter); + +export default (currentPath, currentTab = null) => { + // If navigating directly to a tab, determine the base + // path to initialize router, then set the current route. + const base = currentPath.replace(new RegExp(`/${currentTab}$`), ''); + + const router = new VueRouter({ + mode: 'history', + base, + routes: [{ path: '/:tabId', name: 'tab' }], + }); + + if (currentTab) router.push(`/${currentTab}`); + + return router; +}; diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js index 52ed8bbc798..e677328cd2e 100644 --- a/app/assets/javascripts/issues/show/index.js +++ b/app/assets/javascripts/issues/show/index.js @@ -11,6 +11,7 @@ import IncidentTabs from './components/incidents/incident_tabs.vue'; import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue'; import { issueState } from './constants'; import getIssueStateQuery from './queries/get_issue_state.query.graphql'; +import createRouter from './components/incidents/router'; const bootstrapApollo = (state = {}) => { return apolloProvider.clients.defaultClient.cache.writeQuery({ @@ -36,6 +37,8 @@ export function initIncidentApp(issueData = {}, store) { canUpdateTimelineEvent, iid, issuableId, + currentPath, + currentTab, projectNamespace, projectPath, projectId, @@ -46,12 +49,14 @@ export function initIncidentApp(issueData = {}, store) { } = issueData; const fullPath = `${projectNamespace}/${projectPath}`; + const router = createRouter(currentPath, currentTab); return new Vue({ el, name: 'DescriptionRoot', apolloProvider, store, + router, provide: { issueType: TYPE_INCIDENT, canCreateIncident, diff --git a/app/controllers/concerns/renders_notes.rb b/app/controllers/concerns/renders_notes.rb index f8e3717acee..889d3f0a9d2 100644 --- a/app/controllers/concerns/renders_notes.rb +++ b/app/controllers/concerns/renders_notes.rb @@ -24,13 +24,13 @@ module RendersNotes # rubocop: disable CodeReuse/ActiveRecord def preload_noteable_for_regular_notes(notes) - ActiveRecord::Associations::Preloader.new.preload(notes.reject(&:for_commit?), :noteable) + ActiveRecord::Associations::Preloader.new(records: notes.reject(&:for_commit?), associations: :noteable).call end # rubocop: enable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord def preload_author_status(notes) - ActiveRecord::Associations::Preloader.new.preload(notes, { author: :status }) + ActiveRecord::Associations::Preloader.new(records: notes, associations: { author: :status }).call end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 9323d266cd5..b663a75f04a 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -43,7 +43,10 @@ class Profiles::NotificationsController < Profiles::ApplicationController .preload_source_route projects = project_notifications.map(&:source) - ActiveRecord::Associations::Preloader.new.preload(projects, { namespace: [:route, :owner], group: [] }) + ActiveRecord::Associations::Preloader.new( + records: projects, + associations: { namespace: [:route, :owner], group: [] } + ).call Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute project_notifications.select { |notification| current_user.can?(:read_project, notification.source) } diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index f19f143816f..1e17dd586c7 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -98,7 +98,7 @@ class Projects::BranchesController < Projects::ApplicationController if success render json: { name: branch_name, url: project_tree_url(@project, branch_name) } else - render json: result[:messsage], status: :unprocessable_entity + render json: result[:message], status: :unprocessable_entity end end end diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb index bb91f84de99..99e68991836 100644 --- a/app/finders/autocomplete/users_finder.rb +++ b/app/finders/autocomplete/users_finder.rb @@ -98,7 +98,7 @@ module Autocomplete # rubocop: disable CodeReuse/ActiveRecord def preload_associations(items) - ActiveRecord::Associations::Preloader.new.preload(items, :status) + ActiveRecord::Associations::Preloader.new(records: items, associations: :status).call end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb index 35d30827561..561c61e3b27 100644 --- a/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb +++ b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb @@ -15,7 +15,7 @@ module Resolvers def find_job_artifacts BatchLoader::GraphQL.for(pipeline).batch do |pipelines, loader| - ActiveRecord::Associations::Preloader.new.preload(pipelines, :job_artifacts) # rubocop: disable CodeReuse/ActiveRecord + ActiveRecord::Associations::Preloader.new(records: pipelines, associations: :job_artifacts).call # rubocop: disable CodeReuse/ActiveRecord pipelines.each { |pl| loader.call(pl, pl.job_artifacts) } end diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb index 2352a21bd87..20661da8d94 100644 --- a/app/graphql/types/board_list_type.rb +++ b/app/graphql/types/board_list_type.rb @@ -55,7 +55,7 @@ module Types # board lists have a data dependency on label - so we batch load them here def title BatchLoader::GraphQL.for(object).batch do |lists, callback| - ActiveRecord::Associations::Preloader.new.preload(lists, :label) # rubocop: disable CodeReuse/ActiveRecord + ActiveRecord::Associations::Preloader.new(records: lists, associations: :label).call # rubocop: disable CodeReuse/ActiveRecord # all list titles are preloaded at this point lists.each { |list| callback.call(list, list.title) } diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 46d2d2c42d9..81d083bd082 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -281,7 +281,9 @@ module IssuablesHelper { hasLinkedAlerts: issue.alert_management_alerts.any?, - canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issue) + canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issue), + currentPath: url_for(safe_params), + currentTab: safe_params[:incident_tab] } end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0c2332d8012..9749703bb48 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -55,7 +55,9 @@ module Ci has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', foreign_key: :job_id, inverse_of: :job end - has_one :runner_machine, through: :metadata, class_name: 'Ci::RunnerMachine' + has_one :runner_machine_build, class_name: 'Ci::RunnerMachineBuild', foreign_key: :build_id, inverse_of: :build, + autosave: true + has_one :runner_machine, through: :runner_machine_build, class_name: 'Ci::RunnerMachine' has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, foreign_key: :build_id, inverse_of: :build has_one :trace_metadata, class_name: 'Ci::BuildTraceMetadata', foreign_key: :build_id, inverse_of: :build @@ -132,7 +134,7 @@ module Ci scope :eager_load_job_artifacts, -> { includes(:job_artifacts) } scope :eager_load_tags, -> { includes(:tags) } - scope :eager_load_for_archiving_trace, -> { includes(:project, :pending_state) } + scope :eager_load_for_archiving_trace, -> { preload(:project, :pending_state) } scope :eager_load_everything, -> do includes( @@ -808,7 +810,7 @@ module Ci return unless project return if user&.blocked? - ActiveRecord::Associations::Preloader.new.preload([self], { runner: :tags }) + ActiveRecord::Associations::Preloader.new(records: [self], associations: { runner: :tags }).call project.execute_hooks(build_data.dup, :job_hooks) if project.has_active_hooks?(:job_hooks) project.execute_integrations(build_data.dup, :job_hooks) if project.has_active_integrations?(:job_hooks) diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb index b294afd405d..4b2be446fe3 100644 --- a/app/models/ci/build_metadata.rb +++ b/app/models/ci/build_metadata.rb @@ -10,15 +10,17 @@ module Ci include Presentable include ChronicDurationAttribute include Gitlab::Utils::StrongMemoize + include IgnorableColumns self.table_name = 'p_ci_builds_metadata' self.primary_key = 'id' partitionable scope: :build + ignore_column :runner_machine_id, remove_with: '16.0', remove_after: '2023-04-22' + belongs_to :build, class_name: 'CommitStatus' belongs_to :project - belongs_to :runner_machine, class_name: 'Ci::RunnerMachine' before_create :set_build_project diff --git a/app/models/ci/runner_machine.rb b/app/models/ci/runner_machine.rb index 78f2ad48c82..ac892b3304f 100644 --- a/app/models/ci/runner_machine.rb +++ b/app/models/ci/runner_machine.rb @@ -14,8 +14,8 @@ module Ci belongs_to :runner - has_many :build_metadata, class_name: 'Ci::BuildMetadata' - has_many :builds, through: :build_metadata, class_name: 'Ci::Build' + has_many :runner_machine_builds, inverse_of: :runner_machine, class_name: 'Ci::RunnerMachineBuild' + has_many :builds, through: :runner_machine_builds, class_name: 'Ci::Build' belongs_to :runner_version, inverse_of: :runner_machines, primary_key: :version, foreign_key: :version, class_name: 'Ci::RunnerVersion' diff --git a/app/models/ci/runner_machine_build.rb b/app/models/ci/runner_machine_build.rb new file mode 100644 index 00000000000..ac2b258557a --- /dev/null +++ b/app/models/ci/runner_machine_build.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Ci + class RunnerMachineBuild < Ci::ApplicationRecord + include Ci::Partitionable + include PartitionedTable + + self.table_name = :p_ci_runner_machine_builds + self.primary_key = :build_id + + partitionable scope: :build + partitioned_by :partition_id, + strategy: :ci_sliding_list, + next_partition_if: proc { false }, + detach_partition_if: proc { false } + + belongs_to :build, inverse_of: :runner_machine_build, class_name: 'Ci::Build' + belongs_to :runner_machine, inverse_of: :runner_machine_builds, class_name: 'Ci::RunnerMachine' + + validates :build, presence: true + validates :runner_machine, presence: true + end +end diff --git a/app/models/concerns/ci/partitionable.rb b/app/models/concerns/ci/partitionable.rb index 64f8a04c19f..fa0c2221968 100644 --- a/app/models/concerns/ci/partitionable.rb +++ b/app/models/concerns/ci/partitionable.rb @@ -36,6 +36,7 @@ module Ci Ci::Pipeline Ci::PendingBuild Ci::RunningBuild + Ci::RunnerMachineBuild Ci::PipelineVariable Ci::Sources::Pipeline Ci::Stage diff --git a/app/models/concerns/partitioned_table.rb b/app/models/concerns/partitioned_table.rb index f95f9dd8ad7..c322a736e79 100644 --- a/app/models/concerns/partitioned_table.rb +++ b/app/models/concerns/partitioned_table.rb @@ -8,7 +8,8 @@ module PartitionedTable PARTITIONING_STRATEGIES = { monthly: Gitlab::Database::Partitioning::MonthlyStrategy, - sliding_list: Gitlab::Database::Partitioning::SlidingListStrategy + sliding_list: Gitlab::Database::Partitioning::SlidingListStrategy, + ci_sliding_list: Gitlab::Database::Partitioning::CiSlidingListStrategy }.freeze def partitioned_by(partitioning_key, strategy:, **kwargs) diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index 262839a3fa6..d70aad4e9ae 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -99,39 +99,11 @@ module Routable end def full_name - # We have to test for persistence as the cache key uses #updated_at - return (route&.name || build_full_name) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops) - - # Return the name as-is if the parent is missing - return name if route.nil? && parent.nil? && name.present? - - # If the route is already preloaded, return directly, preventing an extra load - return route.name if route_loaded? && route.present? - - # Similarly, we can allow the build if the parent is loaded - return build_full_name if parent_loaded? - - Gitlab::Cache.fetch_once([cache_key, :full_name]) do - route&.name || build_full_name - end + full_attribute(:name) end def full_path - # We have to test for persistence as the cache key uses #updated_at - return (route&.path || build_full_path) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops) - - # Return the path as-is if the parent is missing - return path if route.nil? && parent.nil? && path.present? - - # If the route is already preloaded, return directly, preventing an extra load - return route.path if route_loaded? && route.present? - - # Similarly, we can allow the build if the parent is loaded - return build_full_path if parent_loaded? - - Gitlab::Cache.fetch_once([cache_key, :full_path]) do - route&.path || build_full_path - end + full_attribute(:path) end # Overriden in the Project model @@ -163,6 +135,31 @@ module Routable private + # rubocop: disable GitlabSecurity/PublicSend + def full_attribute(attribute) + attribute_from_route_or_self = ->(attribute) do + route&.public_send(attribute) || send("build_full_#{attribute}") + end + + unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops) + return attribute_from_route_or_self.call(attribute) + end + + # Return the attribute as-is if the parent is missing + return public_send(attribute) if route.nil? && parent.nil? && public_send(attribute).present? + + # If the route is already preloaded, return directly, preventing an extra load + return route.public_send(attribute) if route_loaded? && route.present? && route.public_send(attribute) + + # Similarly, we can allow the build if the parent is loaded + return send("build_full_#{attribute}") if parent_loaded? + + Gitlab::Cache.fetch_once([cache_key, :"full_#{attribute}"]) do + attribute_from_route_or_self.call(attribute) + end + end + # rubocop: enable GitlabSecurity/PublicSend + def set_path_errors route_path_errors = self.errors.delete(:"route.path") route_path_errors&.each do |msg| diff --git a/app/models/draft_note.rb b/app/models/draft_note.rb index 9f7977fce68..ffc04f9bf90 100644 --- a/app/models/draft_note.rb +++ b/app/models/draft_note.rb @@ -108,7 +108,7 @@ class DraftNote < ApplicationRecord end def self.preload_author(draft_notes) - ActiveRecord::Associations::Preloader.new.preload(draft_notes, { author: :status }) + ActiveRecord::Associations::Preloader.new(records: draft_notes, associations: { author: :status }).call end def diff_file diff --git a/app/models/group.rb b/app/models/group.rb index 38eb11a0d74..d325d1d351a 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -817,8 +817,10 @@ class Group < Namespace end def preload_shared_group_links - preloader = ActiveRecord::Associations::Preloader.new - preloader.preload(self, shared_with_group_links: [shared_with_group: :route]) + ActiveRecord::Associations::Preloader.new( + records: [self], + associations: { shared_with_group_links: [shared_with_group: :route] } + ).call end def update_shared_runners_setting!(state) diff --git a/app/models/members_preloader.rb b/app/models/members_preloader.rb index ba7e4b39989..169ce49b4d3 100644 --- a/app/models/members_preloader.rb +++ b/app/models/members_preloader.rb @@ -8,12 +8,17 @@ class MembersPreloader end def preload_all - ActiveRecord::Associations::Preloader.new.preload(members, :user) - ActiveRecord::Associations::Preloader.new.preload(members, :source) - ActiveRecord::Associations::Preloader.new.preload(members, :created_by) - ActiveRecord::Associations::Preloader.new.preload(members, user: :status) - ActiveRecord::Associations::Preloader.new.preload(members, user: :u2f_registrations) - ActiveRecord::Associations::Preloader.new.preload(members, user: :webauthn_registrations) if Feature.enabled?(:webauthn) + user_associations = [:status, :u2f_registrations] + user_associations << :webauthn_registrations if Feature.enabled?(:webauthn) + + ActiveRecord::Associations::Preloader.new( + records: members, + associations: [ + :source, + :created_by, + { user: user_associations } + ] + ).call end end diff --git a/app/models/preloaders/commit_status_preloader.rb b/app/models/preloaders/commit_status_preloader.rb index 535dd24ba6b..79c2549e371 100644 --- a/app/models/preloaders/commit_status_preloader.rb +++ b/app/models/preloaders/commit_status_preloader.rb @@ -9,10 +9,11 @@ module Preloaders end def execute(relations) - preloader = ActiveRecord::Associations::Preloader.new - CLASSES.each do |klass| - preloader.preload(objects(klass), associations(klass, relations)) + ActiveRecord::Associations::Preloader.new( + records: objects(klass), + associations: associations(klass, relations) + ).call end end diff --git a/app/models/preloaders/labels_preloader.rb b/app/models/preloaders/labels_preloader.rb index b6e73c1cd02..2a3175be420 100644 --- a/app/models/preloaders/labels_preloader.rb +++ b/app/models/preloaders/labels_preloader.rb @@ -19,11 +19,20 @@ module Preloaders end def preload_all - preloader = ActiveRecord::Associations::Preloader.new + ActiveRecord::Associations::Preloader.new( + records: labels, + associations: { parent_container: :route } + ).call - preloader.preload(labels, parent_container: :route) - preloader.preload(labels.select { |l| l.is_a? ProjectLabel }, { project: [:project_feature, namespace: :route] }) - preloader.preload(labels.select { |l| l.is_a? GroupLabel }, { group: :route }) + ActiveRecord::Associations::Preloader.new( + records: labels.select { |l| l.is_a? ProjectLabel }, + associations: { project: [:project_feature, namespace: :route] } + ).call + + ActiveRecord::Associations::Preloader.new( + records: labels.select { |l| l.is_a? GroupLabel }, + associations: { group: :route } + ).call labels.each do |label| label.lazy_subscription(user) diff --git a/app/models/preloaders/project_policy_preloader.rb b/app/models/preloaders/project_policy_preloader.rb index fe9db3464c7..e16eabf40a1 100644 --- a/app/models/preloaders/project_policy_preloader.rb +++ b/app/models/preloaders/project_policy_preloader.rb @@ -10,7 +10,10 @@ module Preloaders def execute return if projects.is_a?(ActiveRecord::NullRelation) - ActiveRecord::Associations::Preloader.new.preload(projects, { group: :route, namespace: :owner }) + ActiveRecord::Associations::Preloader.new( + records: projects, + associations: { group: :route, namespace: :owner } + ).call ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute end diff --git a/app/models/preloaders/project_root_ancestor_preloader.rb b/app/models/preloaders/project_root_ancestor_preloader.rb index 6192f79ce2c..ccb9d2eab98 100644 --- a/app/models/preloaders/project_root_ancestor_preloader.rb +++ b/app/models/preloaders/project_root_ancestor_preloader.rb @@ -19,7 +19,7 @@ module Preloaders root_ancestors_by_id = root_query.group_by(&:source_id) - ActiveRecord::Associations::Preloader.new.preload(@projects, :namespace) + ActiveRecord::Associations::Preloader.new(records: @projects, associations: :namespace).call @projects.each do |project| root_ancestor = root_ancestors_by_id[project.id]&.first project.namespace.root_ancestor = root_ancestor if root_ancestor.present? diff --git a/app/models/project.rb b/app/models/project.rb index 20011b073ee..96e3a9e0f8f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1079,8 +1079,10 @@ class Project < ApplicationRecord end def preload_protected_branches - preloader = ActiveRecord::Associations::Preloader.new - preloader.preload(self, protected_branches: [:push_access_levels, :merge_access_levels]) + ActiveRecord::Associations::Preloader.new( + records: [self], + associations: { protected_branches: [:push_access_levels, :merge_access_levels] } + ).call end # returns all ancestor-groups upto but excluding the given namespace diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb index efffc1bd6dc..13610d37a74 100644 --- a/app/models/resource_label_event.rb +++ b/app/models/resource_label_event.rb @@ -29,9 +29,8 @@ class ResourceLabelEvent < ResourceEvent labels = events.map(&:label).compact project_labels, group_labels = labels.partition { |label| label.is_a? ProjectLabel } - preloader = ActiveRecord::Associations::Preloader.new - preloader.preload(project_labels, { project: :project_feature }) - preloader.preload(group_labels, :group) + ActiveRecord::Associations::Preloader.new(records: project_labels, associations: { project: :project_feature }).call + ActiveRecord::Associations::Preloader.new(records: group_labels, associations: :group).call end def issuable diff --git a/app/presenters/README.md b/app/presenters/README.md index e2461580107..5b600e8f2b2 100644 --- a/app/presenters/README.md +++ b/app/presenters/README.md @@ -165,15 +165,15 @@ however, there is a risk that it accidentally overrides important logic. For example, [this production incident](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5498) was caused by [including `ActionView::Helpers::UrlHelper` in a presenter](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537/diffs#4b581cff00ef3cc9780efd23682af383de302e7d_3_3). -The `tag` accesor in `Ci::Build` was accidentally overridden by `ActionView::Helpers::TagHelper#tag`, -and as a conseuqence, a wrong `tag` value was persited into database. +The `tag` accessor in `Ci::Build` was accidentally overridden by `ActionView::Helpers::TagHelper#tag`, +and as a consequence, a wrong `tag` value was persisted into database. -Starting from GitLab 14.4, we validate the presenters (specifically all of the subclasses of `Gitlab::View::Presenter::Delegated`) +Starting from GitLab 14.4, we [validate](../../lib/gitlab/utils/delegator_override/validator.rb) the presenters (specifically all of the subclasses of `Gitlab::View::Presenter::Delegated`) that they do not accidentally override core/backend logic. In such case, a pipeline in merge requests fails with an error message, here is an example: ```plaintext -We've detected that a presetner is overriding a specific method(s) on a subject model. +We've detected that a presenter is overriding a specific method(s) on a subject model. There is a risk that it accidentally modifies the backend/core logic that leads to production incident. Please follow https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/presenters/README.md#validate-accidental-overrides to resolve this error with caution. @@ -193,7 +193,7 @@ Here are the potential solutions: ### How to use the `Gitlab::Utils::DelegatorOverride` validator -If a presenter class inhertis from `Gitlab::View::Presenter::Delegated`, +If a presenter class inherits from `Gitlab::View::Presenter::Delegated`, you should define what object class is presented: ```ruby @@ -201,7 +201,7 @@ class WebHookLogPresenter < Gitlab::View::Presenter::Delegated presents ::WebHookLog, as: :web_hook_log # This defines that the presenter presents `WebHookLog` Active Record model. ``` -These presenters are validated not to accidentaly override the methods in the presented object. +These presenters are validated not to accidentally override the methods in the presented object. You can run the validation locally with: ```shell diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb index 9a586a1733f..5da0655d21a 100644 --- a/app/presenters/ci/build_runner_presenter.rb +++ b/app/presenters/ci/build_runner_presenter.rb @@ -58,7 +58,7 @@ module Ci # rubocop: disable CodeReuse/ActiveRecord def all_dependencies dependencies = super - ActiveRecord::Associations::Preloader.new.preload(dependencies, :job_artifacts_archive) + ActiveRecord::Associations::Preloader.new(records: dependencies, associations: :job_artifacts_archive).call dependencies end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb index 205da2632c2..8db96ea47c2 100644 --- a/app/services/ci/register_job_service.rb +++ b/app/services/ci/register_job_service.rb @@ -244,7 +244,7 @@ module Ci def assign_runner!(build, params) build.runner_id = runner.id build.runner_session_attributes = params[:session] if params[:session].present? - build.ensure_metadata.runner_machine = runner_machine if runner_machine + build.runner_machine = runner_machine if runner_machine failure_reason, _ = pre_assign_runner_checks.find { |_, check| check.call(build, params) } diff --git a/app/services/issues/referenced_merge_requests_service.rb b/app/services/issues/referenced_merge_requests_service.rb index a69cd324b1e..ff7cf65e757 100644 --- a/app/services/issues/referenced_merge_requests_service.rb +++ b/app/services/issues/referenced_merge_requests_service.rb @@ -6,10 +6,11 @@ module Issues def execute(issue) referenced = referenced_merge_requests(issue) closed_by = closed_by_merge_requests(issue) - preloader = ActiveRecord::Associations::Preloader.new - preloader.preload(referenced + closed_by, - head_pipeline: { project: [:route, { namespace: :route }] }) + ActiveRecord::Associations::Preloader.new( + records: referenced + closed_by, + associations: { head_pipeline: { project: [:route, { namespace: :route }] } } + ).call [sort_by_iid(referenced), sort_by_iid(closed_by)] end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index c660243d336..21946c0e52b 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -2611,7 +2611,7 @@ :urgency: :low :resource_boundary: :unknown :weight: 1 - :idempotent: false + :idempotent: true :tags: [] - :name: group_export :worker_name: GroupExportWorker @@ -3070,7 +3070,7 @@ :urgency: :low :resource_boundary: :unknown :weight: 1 - :idempotent: false + :idempotent: true :tags: [] - :name: project_export :worker_name: ProjectExportWorker diff --git a/app/workers/group_destroy_worker.rb b/app/workers/group_destroy_worker.rb index 92195d3fe16..a116944feb9 100644 --- a/app/workers/group_destroy_worker.rb +++ b/app/workers/group_destroy_worker.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class GroupDestroyWorker # rubocop:disable Scalability/IdempotentWorker +class GroupDestroyWorker include ApplicationWorker data_consistency :always @@ -10,6 +10,9 @@ class GroupDestroyWorker # rubocop:disable Scalability/IdempotentWorker feature_category :subgroups + idempotent! + deduplicate :until_executed, ttl: 2.hours + def perform(group_id, user_id) begin group = Group.find(group_id) diff --git a/app/workers/project_destroy_worker.rb b/app/workers/project_destroy_worker.rb index 45d0ebd2b65..181eebe56e8 100644 --- a/app/workers/project_destroy_worker.rb +++ b/app/workers/project_destroy_worker.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ProjectDestroyWorker # rubocop:disable Scalability/IdempotentWorker +class ProjectDestroyWorker include ApplicationWorker data_consistency :always @@ -10,6 +10,9 @@ class ProjectDestroyWorker # rubocop:disable Scalability/IdempotentWorker feature_category :source_code_management + idempotent! + deduplicate :until_executed, ttl: 2.hours + def perform(project_id, user_id, params) project = Project.find(project_id) user = User.find(user_id) diff --git a/config/gitlab_loose_foreign_keys.yml b/config/gitlab_loose_foreign_keys.yml index c4be4cc1800..ca1129ef288 100644 --- a/config/gitlab_loose_foreign_keys.yml +++ b/config/gitlab_loose_foreign_keys.yml @@ -280,6 +280,10 @@ vulnerability_occurrence_pipelines: - table: ci_pipelines column: pipeline_id on_delete: async_delete +vulnerability_state_transitions: + - table: ci_pipelines + column: state_changed_at_pipeline_id + on_delete: async_nullify vulnerability_statistics: - table: ci_pipelines column: latest_pipeline_id diff --git a/config/initializers/active_record_preloader.rb b/config/initializers/active_record_preloader.rb index 198c97cb849..19ca380a866 100644 --- a/config/initializers/active_record_preloader.rb +++ b/config/initializers/active_record_preloader.rb @@ -3,6 +3,17 @@ module ActiveRecord module Associations class Preloader + def initialize(records: nil, associations: nil) + super() + + @records = records + @associations = associations + end + + def call + preload(@records, @associations) + end + class NullPreloader def self.new(*args, **kwargs) self diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb index e7f29ee1a84..572c8439ec1 100644 --- a/config/initializers/postgres_partitioning.rb +++ b/config/initializers/postgres_partitioning.rb @@ -5,7 +5,8 @@ Gitlab::Database::Partitioning.register_models( AuditEvent, WebHookLog, LooseForeignKeys::DeletedRecord, - Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog + Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog, + Ci::RunnerMachineBuild ]) if Gitlab.ee? diff --git a/config/metrics/objects_schemas/index_inconsistencies_metric.json b/config/metrics/objects_schemas/index_inconsistencies_metric.json new file mode 100644 index 00000000000..635cfa64d95 --- /dev/null +++ b/config/metrics/objects_schemas/index_inconsistencies_metric.json @@ -0,0 +1,19 @@ +{ + "type": "array", + "items": { + "type": [ + { + "type": "object", + "properties": { + "object_name": { + "type": "string" + }, + "type": { + "type": "string", + "description": "Type of index inconsistency" + } + } + } + ] + } +} diff --git a/config/metrics/settings/20230203164341_index_inconsistencies_metric.yml b/config/metrics/settings/20230203164341_index_inconsistencies_metric.yml new file mode 100644 index 00000000000..5076eb9cdd8 --- /dev/null +++ b/config/metrics/settings/20230203164341_index_inconsistencies_metric.yml @@ -0,0 +1,25 @@ +--- +key_path: index_inconsistencies +name: "index_inconsistencies" +description: "List the index inconsistencies in the database" +product_section: enablement +product_stage: enablement +product_group: database +product_category: database +value_type: object +status: active +milestone: "15.10" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111015 +time_frame: none +data_source: system +data_category: optional +instrumentation_class: IndexInconsistenciesMetric +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +value_json_schema: "config/metrics/objects_schemas/index_inconsistencies_metric.json" diff --git a/config/routes/issues.rb b/config/routes/issues.rb index 25e59022272..13fdde5841b 100644 --- a/config/routes/issues.rb +++ b/config/routes/issues.rb @@ -14,6 +14,10 @@ resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do post :create_merge_request get :discussions, format: :json get '/designs(/*vueroute)', to: 'issues#designs', as: :designs, format: false + get '/:incident_tab', + action: :show, + as: :incident_issue, + constraints: { incident_tab: /timeline|metrics|alerts/ } end collection do @@ -23,9 +27,10 @@ resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do post :export_csv scope :incident do - get '/:id', + get '/:id(/:incident_tab)', to: 'incidents#show', - as: :incident + as: :incident, + constraints: { incident_tab: /timeline|metrics|alerts/ } end end diff --git a/db/docs/p_ci_runner_machine_builds.yml b/db/docs/p_ci_runner_machine_builds.yml index f0e8ed26caf..8ffac67fb94 100644 --- a/db/docs/p_ci_runner_machine_builds.yml +++ b/db/docs/p_ci_runner_machine_builds.yml @@ -1,6 +1,6 @@ ---- table_name: p_ci_runner_machine_builds -classes: [] +classes: +- Ci::RunnerMachineBuild feature_categories: - runner_fleet description: Relationships between builds and runner machines diff --git a/db/migrate/20230217232554_add_state_changed_in_to_vulnerability_state_transitions.rb b/db/migrate/20230217232554_add_state_changed_in_to_vulnerability_state_transitions.rb new file mode 100644 index 00000000000..6a8b3b87e21 --- /dev/null +++ b/db/migrate/20230217232554_add_state_changed_in_to_vulnerability_state_transitions.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddStateChangedInToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.1] + def up + add_column :vulnerability_state_transitions, :state_changed_at_pipeline_id, :bigint + end + + def down + remove_column :vulnerability_state_transitions, :state_changed_at_pipeline_id + end +end diff --git a/db/migrate/20230228092612_add_index_next_over_limit_check_at_asc_order_synchronously.rb b/db/migrate/20230228092612_add_index_next_over_limit_check_at_asc_order_synchronously.rb new file mode 100644 index 00000000000..a811b67bb43 --- /dev/null +++ b/db/migrate/20230228092612_add_index_next_over_limit_check_at_asc_order_synchronously.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexNextOverLimitCheckAtAscOrderSynchronously < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + TABLE_NAME = 'namespace_details' + INDEX_NAME = 'index_next_over_limit_check_at_asc_order' + COLUMN = 'next_over_limit_check_at' + + def up + add_concurrent_index TABLE_NAME, COLUMN, name: INDEX_NAME, order: { next_over_limit_check_at: 'ASC NULLS FIRST' } + end + + def down + remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME + end +end diff --git a/db/post_migrate/20230219191034_add_pipeline_fk_to_vulnerability_state_transitions.rb b/db/post_migrate/20230219191034_add_pipeline_fk_to_vulnerability_state_transitions.rb new file mode 100644 index 00000000000..5c09c75861a --- /dev/null +++ b/db/post_migrate/20230219191034_add_pipeline_fk_to_vulnerability_state_transitions.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddPipelineFkToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = 'index_vulnerability_state_transitions_on_pipeline_id' + + def up + add_concurrent_index :vulnerability_state_transitions, :state_changed_at_pipeline_id, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :vulnerability_state_transitions, INDEX_NAME + end +end diff --git a/db/post_migrate/20230227151608_validate_fk_on_ci_build_trace_metadata_partition_id_and_build_id.rb b/db/post_migrate/20230227151608_validate_fk_on_ci_build_trace_metadata_partition_id_and_build_id.rb new file mode 100644 index 00000000000..b95c416c128 --- /dev/null +++ b/db/post_migrate/20230227151608_validate_fk_on_ci_build_trace_metadata_partition_id_and_build_id.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class ValidateFkOnCiBuildTraceMetadataPartitionIdAndBuildId < Gitlab::Database::Migration[2.1] + TABLE_NAME = :ci_build_trace_metadata + FK_NAME = :fk_rails_aebc78111f_p + COLUMNS = [:partition_id, :build_id] + + def up + validate_foreign_key(TABLE_NAME, COLUMNS, name: FK_NAME) + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230227151609_remove_fk_to_ci_builds_ci_build_trace_metadata_on_build_id.rb b/db/post_migrate/20230227151609_remove_fk_to_ci_builds_ci_build_trace_metadata_on_build_id.rb new file mode 100644 index 00000000000..16e24d7ed4c --- /dev/null +++ b/db/post_migrate/20230227151609_remove_fk_to_ci_builds_ci_build_trace_metadata_on_build_id.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class RemoveFkToCiBuildsCiBuildTraceMetadataOnBuildId < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + SOURCE_TABLE_NAME = :ci_build_trace_metadata + TARGET_TABLE_NAME = :ci_builds + COLUMN = :build_id + TARGET_COLUMN = :id + FK_NAME = :fk_rails_aebc78111f + + def up + with_lock_retries do + remove_foreign_key_if_exists( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + name: FK_NAME, + reverse_lock_order: true + ) + end + end + + def down + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: COLUMN, + target_column: TARGET_COLUMN, + validate: true, + reverse_lock_order: true, + on_delete: :cascade, + name: FK_NAME + ) + end +end diff --git a/db/schema_migrations/20230217232554 b/db/schema_migrations/20230217232554 new file mode 100644 index 00000000000..501e10db401 --- /dev/null +++ b/db/schema_migrations/20230217232554 @@ -0,0 +1 @@ +56880a7008d06e9a30337cca7affbe4cdb796b8ef1ccc8b3fc8503af172281cb \ No newline at end of file diff --git a/db/schema_migrations/20230219191034 b/db/schema_migrations/20230219191034 new file mode 100644 index 00000000000..911869229b3 --- /dev/null +++ b/db/schema_migrations/20230219191034 @@ -0,0 +1 @@ +f3be6612c3669066d9a805bf56cae7b3f9a1b6bdaee1bdb3e3f9a596ed3cecef \ No newline at end of file diff --git a/db/schema_migrations/20230227151608 b/db/schema_migrations/20230227151608 new file mode 100644 index 00000000000..333d71b1789 --- /dev/null +++ b/db/schema_migrations/20230227151608 @@ -0,0 +1 @@ +b43ebf61392e2857bd38f783f1ae46c4adce76a94dd8e7aa64fc02f234991229 \ No newline at end of file diff --git a/db/schema_migrations/20230227151609 b/db/schema_migrations/20230227151609 new file mode 100644 index 00000000000..ec320e3c256 --- /dev/null +++ b/db/schema_migrations/20230227151609 @@ -0,0 +1 @@ +c2ac227a2e1a51423b043db9e992a519c096af8a309d3c1074fbd8bd744b4e3b \ No newline at end of file diff --git a/db/schema_migrations/20230228092612 b/db/schema_migrations/20230228092612 new file mode 100644 index 00000000000..ad52eedb797 --- /dev/null +++ b/db/schema_migrations/20230228092612 @@ -0,0 +1 @@ +79c17f4dfb9a208057562c8a9898fda4c1fa8819a3b7a1e594037fd8263aba6f \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 19171a90734..5e44f1f9d4e 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -23871,6 +23871,7 @@ CREATE TABLE vulnerability_state_transitions ( author_id bigint, comment text, dismissal_reason smallint, + state_changed_at_pipeline_id bigint, CONSTRAINT check_d1ca8ec043 CHECK ((from_state <> to_state)), CONSTRAINT check_fe2eb6a0f3 CHECK ((char_length(comment) <= 50000)) ); @@ -30973,6 +30974,8 @@ CREATE INDEX index_namespaces_storage_limit_exclusions_on_namespace_id ON namesp CREATE INDEX index_namespaces_sync_events_on_namespace_id ON namespaces_sync_events USING btree (namespace_id); +CREATE INDEX index_next_over_limit_check_at_asc_order ON namespace_details USING btree (next_over_limit_check_at NULLS FIRST); + CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text)); CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id); @@ -32305,6 +32308,8 @@ CREATE INDEX index_vulnerability_state_transitions_id_and_vulnerability_id ON vu CREATE INDEX index_vulnerability_state_transitions_on_author_id ON vulnerability_state_transitions USING btree (author_id); +CREATE INDEX index_vulnerability_state_transitions_on_pipeline_id ON vulnerability_state_transitions USING btree (state_changed_at_pipeline_id); + CREATE INDEX index_vulnerability_statistics_on_latest_pipeline_id ON vulnerability_statistics USING btree (latest_pipeline_id); CREATE INDEX index_vulnerability_statistics_on_letter_grade ON vulnerability_statistics USING btree (letter_grade); @@ -36102,10 +36107,7 @@ ALTER TABLE ONLY metrics_dashboard_annotations ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE; ALTER TABLE ONLY ci_build_trace_metadata - ADD CONSTRAINT fk_rails_aebc78111f FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE; - -ALTER TABLE ONLY ci_build_trace_metadata - ADD CONSTRAINT fk_rails_aebc78111f_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT fk_rails_aebc78111f_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY bulk_import_trackers ADD CONSTRAINT fk_rails_aed566d3f3 FOREIGN KEY (bulk_import_entity_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE; diff --git a/doc/architecture/blueprints/runner_tokens/index.md b/doc/architecture/blueprints/runner_tokens/index.md index 039c27b64c6..789869cdc16 100644 --- a/doc/architecture/blueprints/runner_tokens/index.md +++ b/doc/architecture/blueprints/runner_tokens/index.md @@ -183,14 +183,17 @@ CREATE TABLE ci_runners ( ) ``` -The `ci_builds_metadata` table shall reference `ci_runner_machines`. +A new `p_ci_runner_machine_builds` table joins the `ci_runner_machines` and `ci_builds` tables, to avoid +adding more pressure to those tables. We might consider a more efficient way to store `contacted_at` than updating the existing record. ```sql -CREATE TABLE ci_builds_metadata ( - ... +CREATE TABLE p_ci_runner_machine_builds ( + partition_id bigint DEFAULT 100 NOT NULL, + build_id bigint NOT NULL, runner_machine_id bigint NOT NULL -); +) +PARTITION BY LIST (partition_id); CREATE TABLE ci_runner_machines ( id bigint NOT NULL, @@ -378,6 +381,9 @@ scope. | GitLab Rails app | `%15.9` | Rename `ci_runner_machines.machine_xid` column to `system_xid` to be consistent with `system_id` passed in APIs. | | GitLab Rails app | `%15.10` | Drop `ci_runner_machines.machine_xid` column. | | GitLab Rails app | `%15.11` | Remove the ignore rule for `ci_runner_machines.machine_xid` column. | +| GitLab Rails app | `%15.10` | Replace `ci_builds_metadata.runner_machine_id` with a new join table. | +| GitLab Rails app | %15.11 | Drop `ci_builds_metadata.runner_machine_id` column. | +| GitLab Rails app | %16.0 | Remove the ignore rule for `ci_builds_metadata.runner_machine_id` column. | ### Stage 4 - Create runners from the UI diff --git a/doc/development/merge_request_concepts/performance.md b/doc/development/merge_request_concepts/performance.md index 740b8f1607b..3b2a097ea2d 100644 --- a/doc/development/merge_request_concepts/performance.md +++ b/doc/development/merge_request_concepts/performance.md @@ -260,7 +260,7 @@ It re-instantiates project object for each build, instead of using the same in-m In this particular case the workaround is fairly easy: ```ruby -ActiveRecord::Associations::Preloader.new.preload(pipeline, [builds: :project]) +ActiveRecord::Associations::Preloader.new(records: pipeline, associations: [builds: :project]).call pipeline.builds.each do |build| build.to_json(only: [:name], include: [project: { only: [:name]}]) diff --git a/doc/integration/partner_marketplace.md b/doc/integration/partner_marketplace.md index 010ce78c9fd..9266fa7ed48 100644 --- a/doc/integration/partner_marketplace.md +++ b/doc/integration/partner_marketplace.md @@ -1,6 +1,6 @@ --- stage: Fulfillment -group: Commerce Integrations +group: Provision info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/operations/quickstart-guide.md b/doc/operations/quickstart-guide.md deleted file mode 100644 index b661243b3e0..00000000000 --- a/doc/operations/quickstart-guide.md +++ /dev/null @@ -1,229 +0,0 @@ ---- -stage: Monitor -group: Observability -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments ---- - -# GitLab Observability Quickstart - -You can try GitLab Observability by [cloning or forking the project](https://gitlab.com/gitlab-org/opstrace/opstrace.git) and creating a local installation. - -## Prerequisites and dependencies - -To install GitLab Observability Platform (GOP), install and configure the following third-party dependencies. You can do this manually, or [automatically by using asdf](#install-dependencies-using-asdf): - -- [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) for creating a local Kubernetes cluster. -- [Docker](https://docs.docker.com/install) - - [Docker Compose](https://docs.docker.com/compose/compose-v2/) is now part of the `docker` distribution. -- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) for interacting with GitLab Observability. -- [Telepresence](https://www.telepresence.io/) allows you to code and test microservices locally against a remote Kubernetes cluster. -- [jq](https://stedolan.github.io/jq/download/) for some Makefile utilities. -- [Go 1.19](https://go.dev/doc/install). - -The current versions of these dependencies are pinned in the `.tool-versions` file in the project. - -You can run the following commands to check the availability and versions of these dependencies on your machine: - -```shell -kind --version -docker --version -kubectl version -telepresence version -jq --version -go version -``` - -### Run GOP on macOS - -If you're running GOP on macOS, ensure you have enough resources dedicated to Docker Desktop. The recommended minimum is: - -- CPUs: 4+ -- Memory: 8 GB+ -- Swap: 1 GB+ - -It's possible to run GOP with fewer resources, but this specification works. - -### Install dependencies using asdf - -If you install dependencies using [`asdf`](https://asdf-vm.com/#/core-manage-asdf), GOP manages them for you automatically. - -1. If you have not already done so, clone the `opstrace` repository into your preferred location: - - ```shell - git clone https://gitlab.com/gitlab-org/opstrace/opstrace.git - ``` - -1. Change into the project directory: - - ```shell - cd opstrace - ``` - -1. Optional. If you need to install `asdf`, run: - - ```shell - make install-asdf - ``` - -1. Install dependencies using `asdf`: - - ```shell - make bootstrap - ``` - -## Step 1: Create a local Kubernetes cluster with kind - -Make sure Docker Desktop is running. In the `opstrace` project you cloned, run the following command: - -```shell -make kind -``` - -Wait a few minutes while kind creates your Kubernetes cluster. When it's finished, you should see the following message: - -```plaintext -Traffic Manager installed successfully -``` - -Now deploy the scheduler by running the following command in the `opstrace` project: - -```shell -make deploy -``` - -This takes around 1 minute. - -## Step 2: Create a GitLab application for authentication - -You must create a GitLab application to use for authentication. - -In the GitLab instance you'd like to connect with GOP, [create an OAuth application](../integration/oauth_provider.md). -This application can be a user-owned, group-owned or instance-wide application. -In production, you would create a trusted instance-wide application so that users are explicitly authorized without the consent screen. -The following example shows how to configure the application. - -1. Select the API scope and enter `http://localhost/v1/auth/callback` as the redirect URI. - -1. Run the following command to create the secret that holds the authentication data: - - ```shell - kubectl create secret generic \ - --from-literal=gitlab_oauth_client_id= \ - --from-literal=gitlab_oauth_client_secret= \ - --from-literal=internal_endpoint_token= \ - dev-secret - ``` - -1. Replace `` and `` with the values from the GitLab application you just created. -Replace `` with any string if you do not plan to use error tracking. - -You can also view [this MR on how to get the token to test error tracking](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91928). -You must specify all the parameters when creating the secret. - -## Step 3: Create the cluster definition - -1. In your `opstrace` project, run the following command to create a `Cluster.yaml` manifest file: - - ```shell - cat < Cluster.yaml - apiVersion: opstrace.com/v1alpha1 - kind: Cluster - metadata: - name: dev-cluster - spec: - target: kind - goui: - image: "registry.gitlab.com/gitlab-org/opstrace/opstrace-ui/ gitlab-observability-ui:c9fb6e70" - dns: - acmeEmail: "" - dns01Challenge: {} - externalDNSProvider: {} - gitlab: - groupAllowedAccess: '*' - groupAllowedSystemAccess: "6543" - instanceUrl: https://gitlab.com - authSecret: - name: dev-secret - EOF - ``` - -1. Apply the file you just created with the following command: - - ```shell - kubectl apply -f Cluster.yaml - ``` - -1. Run the following command to wait for the cluster to be ready: - - ```shell - kubectl wait --for=condition=ready cluster/dev-cluster --timeout=600s - ``` - -After the previous command exits, the cluster is ready. - -## Step 4: Enable Observability on a GitLab namespace you own - -Go to a namespace you own in the connected GitLab instance and copy the Group ID below the group name. - -GOP can only be enabled for groups you own. -To list all the groups that your user owns, in the upper-left corner, select **Groups > View all Groups**. You then see the **Your groups** tab. - -In your browser, go to `http://localhost/-/{GroupID}`. For example, `http://localhost/-/14485840`. - -Follow the on-screen instructions to enable observability for the namespace. -This can take a couple of minutes if it's the first time observability has been enabled for the root level namespace (GitLab.org in the previous example.) - -Once your namespace has been enabled and is ready, the page automatically redirects you to the GitLab Observability UI. - -## Step 5: Send traces to GOP - -[Follow this guide to send traces to your namespace and monitor them in the UI](https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/docs/guides/user/sending-traces-locally.md). - -## Step 6: Clean up your local GOP - -To tear down your locally running GOP instance, run the following command: - -```shell -make destroy -``` - -## Known issues - -### Incorrect architecture for `kind/node` image - -If your machine has an Apple silicon (M1/M2) chip, you might encounter an architecture problem with the `kind/node` image when running the `make kind` command. For more details, see [issue 1802](https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/1802). - -To fix this problem, you first need to create a Dockerfile. Then build and deploy the image: - -1. Create a new Dockerfile (without a file extension) and paste the following commands: - - ```Dockerfile - FROM --platform=arm64 kindest/node:v1.23.13 - RUN arch - ``` - -1. Save your Dockerfile, then build the image with the following command: - - ```shell - docker build -t tempkind . - ``` - - Do not forget the period at the end. - -1. Create a cluster using your new image with the following command: - - ```shell - kind create cluster --image tempkind - ``` - -### scheduler-controller-manager pod cannot start due to ImagePullBackOff - -If while executing `make deploy` in step 1, the `scheduler-controller-manager` pod cannot start due to `ImagePullBackOff`, you must set the `CI_COMMIT_TAG` to a non-dirty state. By setting the commit tag to the latest commit, you ensure the Docker image can be pulled from the container registry. - -Run the following command to set the commit tag: - -```shell -make kind -export CI_COMMIT_TAG=0.2.0-e1206acf -make deploy -``` diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md index 463330113c3..9190006fd67 100644 --- a/doc/user/group/import/index.md +++ b/doc/user/group/import/index.md @@ -65,16 +65,16 @@ transfer. ### Limits -| Limit | Description | -|:------------|:-------------------------------------------------------------------------------------------------------------------------------------| -| 6 | Maximum number of migrations per minute per user. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386452) in GitLab 15.9. | -| 5 GB | Maximum relation size that can be downloaded from the source instance. | -| 10 GB | Maximum size of a decompressed archive. | -| 210 seconds | Maximum number of seconds to wait for decompressing an archive file. | -| 50 MB | Maximum length an NDJSON row can have. | -| 5 minutes | Maximum number of seconds until an empty export status on source instance is raised. | -| 8 hours | Time until migration times out. | -| 90 minutes | Time the destination is waiting for export to complete. | +| Limit | Description | +|:------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 6 | Maximum number of migrations permitted by a destination GitLab instance per minute per user. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386452) in GitLab 15.9. | +| 5 GB | Maximum relation size that can be downloaded from the source instance. | +| 10 GB | Maximum size of a decompressed archive. | +| 210 seconds | Maximum number of seconds to wait for decompressing an archive file. | +| 50 MB | Maximum length an NDJSON row can have. | +| 5 minutes | Maximum number of seconds until an empty export status on source instance is raised. | +| 8 hours | Time until migration times out. | +| 90 minutes | Time the destination is waiting for export to complete. | ### Visibility rules diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md index a2aad8a3e27..0c733b8de30 100644 --- a/doc/user/profile/personal_access_tokens.md +++ b/doc/user/profile/personal_access_tokens.md @@ -222,7 +222,7 @@ Remember this if you set up an automation pipeline that depends on authenticatio ### Unrevoke a personal access token **(FREE SELF)** -If a personal access token is revoked accidentally by any method, administrators can unrevoke that token. +If a personal access token is revoked accidentally by any method, administrators can unrevoke that token. By default, a daily job deletes revoked tokens at 1:00 AM system time. WARNING: Running the following commands changes data directly. This could be damaging if not done correctly, or under the right conditions. You should first run these commands in a test environment with a backup of the instance ready to be restored, just in case. diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb index fcb7ddb9567..7f4a0359e03 100644 --- a/lib/api/entities/project.rb +++ b/lib/api/entities/project.rb @@ -155,7 +155,7 @@ module API # rubocop: disable CodeReuse/ActiveRecord def self.preload_resource(project) - ActiveRecord::Associations::Preloader.new.preload(project, project_group_links: { group: :route }) + ActiveRecord::Associations::Preloader.new(records: [project], associations: { project_group_links: { group: :route } }).call end def self.preload_relation(projects_relation, options = {}) diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb index 07dc4c02ba8..2143497f084 100644 --- a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb +++ b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb @@ -94,10 +94,10 @@ module Gitlab # rubocop: disable CodeReuse/ActiveRecord def preload_associations(records) - ActiveRecord::Associations::Preloader.new.preload( - records, - MAPPINGS.fetch(subject_class).fetch(:includes_for_query) - ) + ActiveRecord::Associations::Preloader.new( + records: records, + associations: MAPPINGS.fetch(subject_class).fetch(:includes_for_query) + ).call records end diff --git a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb index 140c4a300ca..9deb5072112 100644 --- a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb +++ b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb @@ -67,10 +67,10 @@ module Gitlab # rubocop: disable CodeReuse/ActiveRecord def preload_associations(records) # using preloader instead of includes to avoid AR generating a large column list - ActiveRecord::Associations::Preloader.new.preload( - records, - MAPPINGS.fetch(subject_class).fetch(:includes_for_query) - ) + ActiveRecord::Associations::Preloader.new( + records: records, + associations: MAPPINGS.fetch(subject_class).fetch(:includes_for_query) + ).call records end diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb index 939eaa377aa..ecb0cc20a64 100644 --- a/lib/gitlab/data_builder/pipeline.rb +++ b/lib/gitlab/data_builder/pipeline.rb @@ -45,8 +45,9 @@ module Gitlab # rubocop: disable CodeReuse/ActiveRecord def preload_builds(pipeline, association) - ActiveRecord::Associations::Preloader.new.preload(pipeline, - { + ActiveRecord::Associations::Preloader.new( + records: [pipeline], + associations: { association => { **::Ci::Pipeline::PROJECT_ROUTE_AND_NAMESPACE_ROUTE, runner: :tags, @@ -56,7 +57,7 @@ module Gitlab ci_stage: [] } } - ) + ).call end # rubocop: enable CodeReuse/ActiveRecord diff --git a/lib/gitlab/database/partitioning/ci_sliding_list_strategy.rb b/lib/gitlab/database/partitioning/ci_sliding_list_strategy.rb new file mode 100644 index 00000000000..67cf7018ded --- /dev/null +++ b/lib/gitlab/database/partitioning/ci_sliding_list_strategy.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module Partitioning + class CiSlidingListStrategy < SlidingListStrategy + def initial_partition + partition_name = [table_name.to_s.delete_prefix('p_'), 100].join('_') + + SingleNumericListPartition.new(table_name, 100, partition_name: partition_name) + end + + def validate_and_fix; end + + def after_adding_partitions; end + + def extra_partitions + [] + end + + private + + def ensure_partitioning_column_ignored_or_readonly!; end + end + end + end +end diff --git a/lib/gitlab/database/schema_validation/validators/base_validator.rb b/lib/gitlab/database/schema_validation/validators/base_validator.rb index 2478d446e43..1fd3d7c85c4 100644 --- a/lib/gitlab/database/schema_validation/validators/base_validator.rb +++ b/lib/gitlab/database/schema_validation/validators/base_validator.rb @@ -5,7 +5,7 @@ module Gitlab module SchemaValidation module Validators class BaseValidator - Inconsistency = Struct.new(:name, :statement) + Inconsistency = Struct.new(:type, :object_name, :statement) def initialize(structure_sql, database) @structure_sql = structure_sql @@ -16,7 +16,7 @@ module Gitlab [ ExtraIndexes, MissingIndexes, - WrongIndexes + DifferentDefinitionIndexes ] end @@ -28,8 +28,10 @@ module Gitlab attr_reader :structure_sql, :database - def build_inconsistency(schema_object) - Inconsistency.new(schema_object.name, schema_object.statement) + def build_inconsistency(validator_class, schema_object) + inconsistency_type = validator_class.name.demodulize.underscore + + Inconsistency.new(inconsistency_type, schema_object.name, schema_object.statement) end end end diff --git a/lib/gitlab/database/schema_validation/validators/different_definition_indexes.rb b/lib/gitlab/database/schema_validation/validators/different_definition_indexes.rb new file mode 100644 index 00000000000..d54b62ac1e7 --- /dev/null +++ b/lib/gitlab/database/schema_validation/validators/different_definition_indexes.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module SchemaValidation + module Validators + class DifferentDefinitionIndexes < BaseValidator + def execute + structure_sql.indexes.filter_map do |structure_sql_index| + database_index = database.fetch_index_by_name(structure_sql_index.name) + + next if database_index.nil? + next if database_index.statement == structure_sql_index.statement + + build_inconsistency(self.class, structure_sql_index) + end + end + end + end + end + end +end diff --git a/lib/gitlab/database/schema_validation/validators/extra_indexes.rb b/lib/gitlab/database/schema_validation/validators/extra_indexes.rb index 023052459ff..28384dd7cee 100644 --- a/lib/gitlab/database/schema_validation/validators/extra_indexes.rb +++ b/lib/gitlab/database/schema_validation/validators/extra_indexes.rb @@ -9,7 +9,7 @@ module Gitlab database.indexes.filter_map do |index| next if structure_sql.index_exists?(index.name) - build_inconsistency(index) + build_inconsistency(self.class, index) end end end diff --git a/lib/gitlab/database/schema_validation/validators/missing_indexes.rb b/lib/gitlab/database/schema_validation/validators/missing_indexes.rb index 890c00c58c9..ac0ea0152ba 100644 --- a/lib/gitlab/database/schema_validation/validators/missing_indexes.rb +++ b/lib/gitlab/database/schema_validation/validators/missing_indexes.rb @@ -9,7 +9,7 @@ module Gitlab structure_sql.indexes.filter_map do |index| next if database.index_exists?(index.name) - build_inconsistency(index) + build_inconsistency(self.class, index) end end end diff --git a/lib/gitlab/database/schema_validation/validators/wrong_indexes.rb b/lib/gitlab/database/schema_validation/validators/wrong_indexes.rb deleted file mode 100644 index a92e7158be7..00000000000 --- a/lib/gitlab/database/schema_validation/validators/wrong_indexes.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module SchemaValidation - module Validators - class WrongIndexes < BaseValidator - def execute - structure_sql.indexes.filter_map do |structure_sql_index| - database_index = database.fetch_index_by_name(structure_sql_index.name) - - next if database_index.nil? - next if database_index.statement == structure_sql_index.statement - - build_inconsistency(structure_sql_index) - end - end - end - end - end - end -end diff --git a/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric.rb b/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric.rb new file mode 100644 index 00000000000..409027925d1 --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class IndexInconsistenciesMetric < GenericMetric + value do + runner = Gitlab::Database::SchemaValidation::Runner.new(structure_sql, database, validators: validators) + + inconsistencies = runner.execute + + inconsistencies.map do |inconsistency| + { + object_name: inconsistency.object_name, + inconsistency_type: inconsistency.type + } + end + end + + class << self + private + + def database + database_model = Gitlab::Database.database_base_models[Gitlab::Database::MAIN_DATABASE_NAME] + Gitlab::Database::SchemaValidation::Database.new(database_model.connection) + end + + def structure_sql + stucture_sql_path = Rails.root.join('db/structure.sql') + Gitlab::Database::SchemaValidation::StructureSql.new(stucture_sql_path) + end + + def validators + [ + Gitlab::Database::SchemaValidation::Validators::MissingIndexes, + Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionIndexes, + Gitlab::Database::SchemaValidation::Validators::ExtraIndexes + ] + end + end + end + end + end + end +end diff --git a/lib/tasks/gitlab/tw/codeowners.rake b/lib/tasks/gitlab/tw/codeowners.rake index 8861e8574b3..e6bbbc55cb1 100644 --- a/lib/tasks/gitlab/tw/codeowners.rake +++ b/lib/tasks/gitlab/tw/codeowners.rake @@ -29,7 +29,6 @@ namespace :tw do CodeOwnerRule.new('Configure', '@phillipwells'), CodeOwnerRule.new('Container Registry', '@marcel.amirault'), CodeOwnerRule.new('Contributor Experience', '@eread'), - CodeOwnerRule.new('Conversion', '@kpaizee'), CodeOwnerRule.new('Database', '@aqualls'), CodeOwnerRule.new('Development', '@sselhorn'), CodeOwnerRule.new('Distribution', '@axil'), diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 67b374607f4..2a02f76fa64 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15348,6 +15348,9 @@ msgstr "" msgid "Edit image description" msgstr "" +msgid "Edit image text or link" +msgstr "" + msgid "Edit in pipeline editor" msgstr "" diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 55c148bb66f..600f8047a1d 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -277,6 +277,7 @@ RSpec.describe Projects::BranchesController, feature_category: :source_code_mana create_branch name: "", ref: "" expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(response.body).to include 'Failed to create branch' end end diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 756cb23b7a4..f10adfe5173 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -36,7 +36,7 @@ RSpec.describe 'Database schema', feature_category: :database do ci_build_pending_states: %w[partition_id build_id], ci_build_report_results: %w[partition_id build_id], ci_build_trace_chunks: %w[partition_id build_id], - ci_build_trace_metadata: %w[partition_id], + ci_build_trace_metadata: %w[partition_id build_id], ci_builds: %w[erased_by_id trigger_request_id partition_id], ci_builds_runner_session: %w[partition_id build_id], p_ci_builds_metadata: %w[partition_id], diff --git a/spec/factories/ci/runner_machine_builds.rb b/spec/factories/ci/runner_machine_builds.rb new file mode 100644 index 00000000000..0181def26ba --- /dev/null +++ b/spec/factories/ci/runner_machine_builds.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :ci_runner_machine_build, class: 'Ci::RunnerMachineBuild' do + build factory: :ci_build, scheduling_type: :dag + runner_machine factory: :ci_runner_machine + end +end diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb index 7404ac64cc9..a4449ee2608 100644 --- a/spec/features/incidents/incident_timeline_events_spec.rb +++ b/spec/features/incidents/incident_timeline_events_spec.rb @@ -96,5 +96,6 @@ RSpec.describe 'Incident timeline events', :js, feature_category: :incident_mana it_behaves_like 'for each incident details route', 'add, edit, and delete timeline events', - tab_text: s_('Incident|Timeline') + tab_text: s_('Incident|Timeline'), + tab: 'timeline' end diff --git a/spec/features/incidents/user_views_alert_details_spec.rb b/spec/features/incidents/user_views_alert_details_spec.rb new file mode 100644 index 00000000000..f3d0273071c --- /dev/null +++ b/spec/features/incidents/user_views_alert_details_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'User uploads alerts to incident', :js, feature_category: :incident_management do + let_it_be(:incident) { create(:incident) } + let_it_be(:project) { incident.project } + let_it_be(:user) { create(:user, developer_projects: [project]) } + + context 'with alert' do + let_it_be(:alert) { create(:alert_management_alert, issue_id: incident.id, project: project) } + + shared_examples 'shows alert tab with details' do + specify do + expect(page).to have_link(s_('Incident|Alert details')) + expect(page).to have_content(alert.title) + end + end + + it_behaves_like 'for each incident details route', + 'shows alert tab with details', + tab_text: s_('Incident|Alert details'), + tab: 'alerts' + end + + context 'with no alerts' do + it 'hides the Alert details tab' do + sign_in(user) + visit project_issue_path(project, incident) + + expect(page).not_to have_link(s_('Incident|Alert details')) + end + end +end diff --git a/spec/frontend/boards/components/board_top_bar_spec.js b/spec/frontend/boards/components/board_top_bar_spec.js index faf1547c47e..002e4034e70 100644 --- a/spec/frontend/boards/components/board_top_bar_spec.js +++ b/spec/frontend/boards/components/board_top_bar_spec.js @@ -11,7 +11,7 @@ import ConfigToggle from '~/boards/components/config_toggle.vue'; import IssueBoardFilteredSearch from '~/boards/components/issue_board_filtered_search.vue'; import NewBoardButton from '~/boards/components/new_board_button.vue'; import ToggleFocus from '~/boards/components/toggle_focus.vue'; -import { BoardType } from '~/boards/constants'; +import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import groupBoardQuery from '~/boards/graphql/group_board.query.graphql'; import projectBoardQuery from '~/boards/graphql/project_board.query.graphql'; @@ -116,14 +116,14 @@ describe('BoardTopBar', () => { describe('Apollo boards', () => { it.each` boardType | queryHandler | notCalledHandler - ${BoardType.group} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess} - ${BoardType.project} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess} + ${WORKSPACE_GROUP} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess} + ${WORKSPACE_PROJECT} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess} `('fetches $boardType boards', async ({ boardType, queryHandler, notCalledHandler }) => { createComponent({ provide: { boardType, - isProjectBoard: boardType === BoardType.project, - isGroupBoard: boardType === BoardType.group, + isProjectBoard: boardType === WORKSPACE_PROJECT, + isGroupBoard: boardType === WORKSPACE_GROUP, isApolloBoard: true, }, }); diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js index 28f51e0ecbf..afa304a66ff 100644 --- a/spec/frontend/boards/components/boards_selector_spec.js +++ b/spec/frontend/boards/components/boards_selector_spec.js @@ -5,11 +5,11 @@ import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; import { TEST_HOST } from 'spec/test_constants'; import BoardsSelector from '~/boards/components/boards_selector.vue'; -import { BoardType } from '~/boards/constants'; import groupBoardsQuery from '~/boards/graphql/group_boards.query.graphql'; import projectBoardsQuery from '~/boards/graphql/project_boards.query.graphql'; import groupRecentBoardsQuery from '~/boards/graphql/group_recent_boards.query.graphql'; import projectRecentBoardsQuery from '~/boards/graphql/project_recent_boards.query.graphql'; +import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import createMockApollo from 'helpers/mock_apollo_helper'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import { @@ -228,13 +228,13 @@ describe('BoardsSelector', () => { describe('fetching all boards', () => { it.each` boardType | queryHandler | notCalledHandler - ${BoardType.group} | ${groupBoardsQueryHandlerSuccess} | ${projectBoardsQueryHandlerSuccess} - ${BoardType.project} | ${projectBoardsQueryHandlerSuccess} | ${groupBoardsQueryHandlerSuccess} + ${WORKSPACE_GROUP} | ${groupBoardsQueryHandlerSuccess} | ${projectBoardsQueryHandlerSuccess} + ${WORKSPACE_PROJECT} | ${projectBoardsQueryHandlerSuccess} | ${groupBoardsQueryHandlerSuccess} `('fetches $boardType boards', async ({ boardType, queryHandler, notCalledHandler }) => { createStore(); createComponent({ - isGroupBoard: boardType === BoardType.group, - isProjectBoard: boardType === BoardType.project, + isGroupBoard: boardType === WORKSPACE_GROUP, + isProjectBoard: boardType === WORKSPACE_PROJECT, }); await nextTick(); diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index b830ca1126d..13eb3865354 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -2,13 +2,7 @@ import * as Sentry from '@sentry/browser'; import { cloneDeep } from 'lodash'; import Vue from 'vue'; import Vuex from 'vuex'; -import { - inactiveId, - ISSUABLE, - ListType, - BoardType, - DraggableItemTypes, -} from 'ee_else_ce/boards/constants'; +import { inactiveId, ISSUABLE, ListType, DraggableItemTypes } from 'ee_else_ce/boards/constants'; import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql'; import testAction from 'helpers/vuex_action_helper'; import { @@ -26,7 +20,7 @@ import actions from '~/boards/stores/actions'; import * as types from '~/boards/stores/mutation_types'; import mutations from '~/boards/stores/mutations'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import { TYPE_ISSUE } from '~/issues/constants'; +import { TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import projectBoardMilestones from '~/boards/graphql/project_board_milestones.query.graphql'; import groupBoardMilestones from '~/boards/graphql/group_board_milestones.query.graphql'; @@ -300,8 +294,8 @@ describe('fetchLists', () => { it.each` issuableType | boardType | fullBoardId | isGroup | isProject - ${TYPE_ISSUE} | ${BoardType.group} | ${'gid://gitlab/Board/1'} | ${true} | ${false} - ${TYPE_ISSUE} | ${BoardType.project} | ${'gid://gitlab/Board/1'} | ${false} | ${true} + ${TYPE_ISSUE} | ${WORKSPACE_GROUP} | ${'gid://gitlab/Board/1'} | ${true} | ${false} + ${TYPE_ISSUE} | ${WORKSPACE_PROJECT} | ${'gid://gitlab/Board/1'} | ${false} | ${true} `( 'calls $issuableType query with correct variables', async ({ issuableType, boardType, fullBoardId, isGroup, isProject }) => { diff --git a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js index 380b4b92f2e..0f4fb02a40b 100644 --- a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js +++ b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js @@ -1,4 +1,5 @@ import merge from 'lodash/merge'; +import { nextTick } from 'vue'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { trackIncidentDetailsViewsOptions } from '~/incidents/constants'; import DescriptionComponent from '~/issues/show/components/description.vue'; @@ -11,6 +12,11 @@ import Tracking from '~/tracking'; import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue'; import { descriptionProps } from '../../mock_data/mock_data'; +const push = jest.fn(); +const $router = { + push, +}; + const mockAlert = { __typename: 'AlertManagementAlert', detailsUrl: INVALID_URL, @@ -28,6 +34,8 @@ const defaultMocks = { }, }, }, + $route: { params: {} }, + $router, }; describe('Incident Tabs component', () => { @@ -165,6 +173,40 @@ describe('Incident Tabs component', () => { expect(findActiveTabs()).toHaveLength(1); expect(findActiveTabs().at(0).text()).toBe(incidentTabsI18n.timelineTitle); + expect(push).toHaveBeenCalledWith('/timeline'); + }); + }); + + describe('loading page with tab', () => { + it('shows the timeline tab when timeline path is passed', async () => { + mountComponent({ + mount: mountExtended, + mocks: { $route: { params: { tabId: 'timeline' } } }, + }); + await nextTick(); + expect(findActiveTabs()).toHaveLength(1); + expect(findActiveTabs().at(0).text()).toBe(incidentTabsI18n.timelineTitle); + }); + + it('shows the alerts tab when timeline path is passed', async () => { + mountComponent({ + mount: mountExtended, + mocks: { $route: { params: { tabId: 'alerts' } } }, + hasLinkedAlerts: true, + }); + await nextTick(); + expect(findActiveTabs()).toHaveLength(1); + expect(findActiveTabs().at(0).text()).toBe(incidentTabsI18n.alertsTitle); + }); + + it('shows the metrics tab when metrics path is passed', async () => { + mountComponent({ + mount: mountExtended, + mocks: { $route: { params: { tabId: 'metrics' } } }, + }); + await nextTick(); + expect(findActiveTabs()).toHaveLength(1); + expect(findActiveTabs().at(0).text()).toBe(incidentTabsI18n.metricsTitle); }); }); }); diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 1ae834c0769..d5fff7f3a31 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -430,7 +430,8 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do action: "show", namespace_id: "foo", project_id: "bar", - id: incident.iid + id: incident.iid, + incident_tab: 'timeline' }).permit! end @@ -441,7 +442,9 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do expected_data = { issueType: 'incident', hasLinkedAlerts: false, - canUpdateTimelineEvent: true + canUpdateTimelineEvent: true, + currentPath: "/foo/bar/-/issues/incident/#{incident.iid}/timeline", + currentTab: 'timeline' } expect(helper.issuable_initial_data(incident)).to match(hash_including(expected_data)) diff --git a/spec/lib/gitlab/database/schema_validation/runner_spec.rb b/spec/lib/gitlab/database/schema_validation/runner_spec.rb index e07deec3062..13980cb148b 100644 --- a/spec/lib/gitlab/database/schema_validation/runner_spec.rb +++ b/spec/lib/gitlab/database/schema_validation/runner_spec.rb @@ -32,7 +32,7 @@ RSpec.describe Gitlab::Database::SchemaValidation::Runner, feature_category: :da let(:extra_indexes) { class_double(class_name) } let(:instace_extra_index) { instance_double(class_name, execute: [inconsistency]) } - let(:inconsistency) { instance_double(inconsistency_class_name, name: 'test') } + let(:inconsistency) { instance_double(inconsistency_class_name, object_name: 'test') } let(:validators) { [extra_indexes] } @@ -43,7 +43,7 @@ RSpec.describe Gitlab::Database::SchemaValidation::Runner, feature_category: :da expect(validator).not_to receive(:new).with(structure_sql, database) end - expect(inconsistencies.map(&:name)).to eql ['test'] + expect(inconsistencies.map(&:object_name)).to eql ['test'] end end end diff --git a/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb index adac5b4e579..cf5207aee95 100644 --- a/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb +++ b/spec/lib/gitlab/database/schema_validation/validators/base_validator_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Gitlab::Database::SchemaValidation::Validators::BaseValidator, fe expect(all_validators).to eq([ Gitlab::Database::SchemaValidation::Validators::ExtraIndexes, Gitlab::Database::SchemaValidation::Validators::MissingIndexes, - Gitlab::Database::SchemaValidation::Validators::WrongIndexes + Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionIndexes ]) end end diff --git a/spec/lib/gitlab/database/schema_validation/validators/different_definition_indexes_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/different_definition_indexes_spec.rb new file mode 100644 index 00000000000..b9744c86b80 --- /dev/null +++ b/spec/lib/gitlab/database/schema_validation/validators/different_definition_indexes_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SchemaValidation::Validators::DifferentDefinitionIndexes, + feature_category: :database do + include_examples 'index validators', described_class, ['wrong_index'] +end diff --git a/spec/lib/gitlab/database/schema_validation/validators/wrong_indexes_spec.rb b/spec/lib/gitlab/database/schema_validation/validators/wrong_indexes_spec.rb deleted file mode 100644 index 026f3fb710c..00000000000 --- a/spec/lib/gitlab/database/schema_validation/validators/wrong_indexes_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Database::SchemaValidation::Validators::WrongIndexes, feature_category: :database do - include_examples 'index validators', described_class, ['wrong_index'] -end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index a22b9d11214..73f29f6debe 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -297,6 +297,7 @@ ci_pipelines: - job_artifacts - vulnerabilities_finding_pipelines - vulnerability_findings +- vulnerability_state_transitions - pipeline_config - security_scans - security_findings @@ -396,6 +397,7 @@ builds: - job_artifacts_cyclonedx - job_artifacts_requirements_v2 - runner_machine +- runner_machine_build - runner_session - trace_metadata - terraform_state_versions diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric_spec.rb new file mode 100644 index 00000000000..afc9d610207 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/index_inconsistencies_metric_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::IndexInconsistenciesMetric, feature_category: :database do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'all' } do + let(:expected_value) do + [ + { inconsistency_type: 'wrong_indexes', object_name: 'index_name_1' }, + { inconsistency_type: 'missing_indexes', object_name: 'index_name_2' }, + { inconsistency_type: 'extra_indexes', object_name: 'index_name_3' } + ] + end + + let(:runner) { instance_double(Gitlab::Database::SchemaValidation::Runner, execute: inconsistencies) } + let(:inconsistency_class) { Gitlab::Database::SchemaValidation::Validators::BaseValidator::Inconsistency } + + let(:inconsistencies) do + [ + instance_double(inconsistency_class, object_name: 'index_name_1', type: 'wrong_indexes'), + instance_double(inconsistency_class, object_name: 'index_name_2', type: 'missing_indexes'), + instance_double(inconsistency_class, object_name: 'index_name_3', type: 'extra_indexes') + ] + end + + before do + allow(Gitlab::Database::SchemaValidation::Runner).to receive(:new).and_return(runner) + end + end +end diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb index fb50ba89cd3..c3b445cbbe5 100644 --- a/spec/models/ci/build_metadata_spec.rb +++ b/spec/models/ci/build_metadata_spec.rb @@ -22,7 +22,6 @@ RSpec.describe Ci::BuildMetadata do it { is_expected.to belong_to(:build) } it { is_expected.to belong_to(:project) } - it { is_expected.to belong_to(:runner_machine) } describe '#update_timeout_state' do subject { metadata } diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 29cc94ff13f..6836d1b51ef 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def it { is_expected.to have_many(:pages_deployments).with_foreign_key(:ci_build_id) } it { is_expected.to have_one(:deployment) } - it { is_expected.to have_one(:runner_machine).through(:metadata) } + it { is_expected.to have_one(:runner_machine).through(:runner_machine_build) } it { is_expected.to have_one(:runner_session).with_foreign_key(:build_id) } it { is_expected.to have_one(:trace_metadata).with_foreign_key(:build_id) } it { is_expected.to have_one(:runtime_metadata).with_foreign_key(:build_id) } diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb index db22d8f3a6c..cf2c176816d 100644 --- a/spec/models/ci/processable_spec.rb +++ b/spec/models/ci/processable_spec.rb @@ -83,7 +83,7 @@ RSpec.describe Ci::Processable, feature_category: :continuous_integration do runner_id tag_taggings taggings tags trigger_request_id user_id auto_canceled_by_id retried failure_reason sourced_pipelines sourced_pipeline artifacts_file_store artifacts_metadata_store - metadata runner_machine_id runner_machine runner_session trace_chunks upstream_pipeline_id + metadata runner_machine_build runner_machine runner_session trace_chunks upstream_pipeline_id artifacts_file artifacts_metadata artifacts_size commands resource resource_group_id processed security_scans author pipeline_id report_results pending_state pages_deployments diff --git a/spec/models/ci/runner_machine_build_spec.rb b/spec/models/ci/runner_machine_build_spec.rb new file mode 100644 index 00000000000..b15d232cbb5 --- /dev/null +++ b/spec/models/ci/runner_machine_build_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::RunnerMachineBuild, model: true, feature_category: :runner_fleet do + it { is_expected.to belong_to(:build) } + it { is_expected.to belong_to(:runner_machine) } + + describe 'partitioning' do + context 'with build' do + let(:build) { FactoryBot.build(:ci_build, partition_id: ci_testing_partition_id) } + let(:runner_machine_build) { FactoryBot.build(:ci_runner_machine_build, build: build) } + + it 'sets partition_id to the current partition value' do + expect { runner_machine_build.valid? }.to change { runner_machine_build.partition_id } + .to(ci_testing_partition_id) + end + + context 'when it is already set' do + let(:runner_machine_build) { FactoryBot.build(:ci_runner_machine_build, partition_id: 125) } + + it 'does not change the partition_id value' do + expect { runner_machine_build.valid? }.not_to change { runner_machine_build.partition_id } + end + end + end + + context 'without build' do + let(:runner_machine_build) { FactoryBot.build(:ci_runner_machine_build, build: nil) } + + it { is_expected.to validate_presence_of(:partition_id) } + + it 'does not change the partition_id value' do + expect { runner_machine_build.valid? }.not_to change { runner_machine_build.partition_id } + end + end + end + + describe 'ci_sliding_list partitioning' do + let(:connection) { described_class.connection } + let(:partition_manager) { Gitlab::Database::Partitioning::PartitionManager.new(described_class) } + + let(:partitioning_strategy) { described_class.partitioning_strategy } + + it { expect(partitioning_strategy.missing_partitions).to be_empty } + it { expect(partitioning_strategy.extra_partitions).to be_empty } + it { expect(partitioning_strategy.current_partitions).to include partitioning_strategy.initial_partition } + it { expect(partitioning_strategy.active_partition).to be_present } + end +end diff --git a/spec/models/ci/runner_machine_spec.rb b/spec/models/ci/runner_machine_spec.rb index 6162077a055..dbefd7aa449 100644 --- a/spec/models/ci/runner_machine_spec.rb +++ b/spec/models/ci/runner_machine_spec.rb @@ -7,8 +7,8 @@ RSpec.describe Ci::RunnerMachine, feature_category: :runner_fleet, type: :model it { is_expected.to belong_to(:runner) } it { is_expected.to belong_to(:runner_version).with_foreign_key(:version) } - it { is_expected.to have_many(:build_metadata) } - it { is_expected.to have_many(:builds).through(:build_metadata) } + it { is_expected.to have_many(:runner_machine_builds) } + it { is_expected.to have_many(:builds).through(:runner_machine_builds) } describe 'validation' do it { is_expected.to validate_presence_of(:runner) } diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb index dc1002f3560..0bbe3dea812 100644 --- a/spec/models/concerns/routable_spec.rb +++ b/spec/models/concerns/routable_spec.rb @@ -74,6 +74,17 @@ RSpec.shared_examples 'routable resource with parent' do describe '#full_name' do it { expect(record.full_name).to eq "#{record.parent.human_name} / #{record.name}" } + context 'without route name' do + before do + stub_feature_flags(cached_route_lookups: true) + record.route.update_attribute(:name, nil) + end + + it 'builds full name' do + expect(record.full_name).to eq("#{record.parent.human_name} / #{record.name}") + end + end + it 'hits the cache when not preloaded' do forcibly_hit_cached_lookup(record, :full_name) diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb index 67a73834f2d..2b9ff442f76 100644 --- a/spec/requests/projects/issues_controller_spec.rb +++ b/spec/requests/projects/issues_controller_spec.rb @@ -25,33 +25,23 @@ RSpec.describe Projects::IssuesController, feature_category: :team_planning do end describe 'GET #show' do - include_context 'group project issue' + before do + login_as(user) + end it_behaves_like "observability csp policy", described_class do + include_context 'group project issue' let(:tested_path) do project_issue_path(project, issue) end end - end - - describe 'GET #index.json' do - let_it_be(:public_project) { create(:project, :public) } - it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do - let_it_be(:current_user) { create(:user) } - - before do - sign_in current_user - end - - def request - get project_issues_path(public_project, format: :json), params: { scope: 'all', search: 'test' } - end - end + describe 'incident tabs' do + let_it_be(:incident) { create(:incident, project: project) } - it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit_unauthenticated do - def request - get project_issues_path(public_project, format: :json), params: { scope: 'all', search: 'test' } + it 'responds with selected tab for incidents' do + get incident_issue_project_issue_path(project, incident, 'timeline') + expect(response.body).to match(/"currentTab":"timeline"/) end end end diff --git a/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb index dab125caa60..b8e42843e6f 100644 --- a/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb +++ b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.shared_examples 'for each incident details route' do |example, tab_text:| +RSpec.shared_examples 'for each incident details route' do |example, tab_text:, tab:| before do sign_in(user) visit incident_path @@ -25,4 +25,16 @@ RSpec.shared_examples 'for each incident details route' do |example, tab_text:| it_behaves_like example end + + context "for /-/issues/incident/:id/#{tab} route" do + let(:incident_path) { incident_project_issues_path(project, incident, tab) } + + it_behaves_like example + end + + context "for /-/issues/:id/#{tab} route" do + let(:incident_path) { incident_issue_project_issue_path(project, incident, tab) } + + it_behaves_like example + end end diff --git a/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb index 0a8fd39bc2c..6b0ea9421de 100644 --- a/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb @@ -12,6 +12,8 @@ RSpec.shared_examples "index validators" do |validator, expected_result| ] end + let(:inconsistency_type) { validator.name.demodulize.underscore } + let(:database_name) { 'main' } let(:database_model) { Gitlab::Database.database_base_models[database_name] } @@ -29,7 +31,8 @@ RSpec.shared_examples "index validators" do |validator, expected_result| allow(connection).to receive(:exec_query).and_return(query_result) end - it 'returns extra indexes' do - expect(result.map(&:name)).to match_array(expected_result) + it 'returns index inconsistencies' do + expect(result.map(&:object_name)).to match_array(expected_result) + expect(result.map(&:type)).to all(eql inconsistency_type) end end diff --git a/spec/workers/group_destroy_worker_spec.rb b/spec/workers/group_destroy_worker_spec.rb index 82ae9010a24..fba4573718a 100644 --- a/spec/workers/group_destroy_worker_spec.rb +++ b/spec/workers/group_destroy_worker_spec.rb @@ -2,20 +2,29 @@ require 'spec_helper' -RSpec.describe GroupDestroyWorker do - let(:group) { create(:group) } - let!(:project) { create(:project, namespace: group) } - let(:user) { create(:user) } +RSpec.describe GroupDestroyWorker, feature_category: :subgroups do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, namespace: group) } + let_it_be(:user) { create(:user) } before do group.add_owner(user) end - subject { described_class.new } + subject(:worker) { described_class.new } + + include_examples 'an idempotent worker' do + let(:job_args) { [group.id, user.id] } + + it 'does not change groups when run twice' do + expect { worker.perform(group.id, user.id) }.to change { Group.count }.by(-1) + expect { worker.perform(group.id, user.id) }.not_to change { Group.count } + end + end describe "#perform" do - it "deletes the project" do - subject.perform(group.id, user.id) + it "deletes the group and associated projects" do + worker.perform(group.id, user.id) expect(Group.all).not_to include(group) expect(Project.all).not_to include(project) diff --git a/spec/workers/project_destroy_worker_spec.rb b/spec/workers/project_destroy_worker_spec.rb index 25508928bbf..d699393d7a0 100644 --- a/spec/workers/project_destroy_worker_spec.rb +++ b/spec/workers/project_destroy_worker_spec.rb @@ -2,15 +2,26 @@ require 'spec_helper' -RSpec.describe ProjectDestroyWorker do - let(:project) { create(:project, :repository, pending_delete: true) } - let!(:repository) { project.repository.raw } +RSpec.describe ProjectDestroyWorker, feature_category: :source_code_management do + let_it_be(:project) { create(:project, :repository, pending_delete: true) } + let_it_be(:repository) { project.repository.raw } - subject { described_class.new } + let(:user) { project.first_owner } + + subject(:worker) { described_class.new } + + include_examples 'an idempotent worker' do + let(:job_args) { [project.id, user.id, {}] } + + it 'does not change projects when run twice' do + expect { worker.perform(project.id, user.id, {}) }.to change { Project.count }.by(-1) + expect { worker.perform(project.id, user.id, {}) }.not_to change { Project.count } + end + end describe '#perform' do it 'deletes the project' do - subject.perform(project.id, project.first_owner.id, {}) + worker.perform(project.id, user.id, {}) expect(Project.all).not_to include(project) expect(repository).not_to exist @@ -18,13 +29,13 @@ RSpec.describe ProjectDestroyWorker do it 'does not raise error when project could not be found' do expect do - subject.perform(-1, project.first_owner.id, {}) + worker.perform(-1, user.id, {}) end.not_to raise_error end it 'does not raise error when user could not be found' do expect do - subject.perform(project.id, -1, {}) + worker.perform(project.id, -1, {}) end.not_to raise_error end end diff --git a/workhorse/go.mod b/workhorse/go.mod index 02fa22a47d6..6e3f47b9afc 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -26,7 +26,7 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/smartystreets/goconvey v1.7.2 github.com/stretchr/testify v1.8.1 - gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc42 + gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc43 gitlab.com/gitlab-org/golang-archive-zip v0.1.1 gitlab.com/gitlab-org/labkit v1.17.0 gocloud.dev v0.28.0 diff --git a/workhorse/go.sum b/workhorse/go.sum index c266518925e..2240d85273e 100644 --- a/workhorse/go.sum +++ b/workhorse/go.sum @@ -1847,8 +1847,8 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc42 h1:mV3bwpQOlw+3+iAfqK6hmAZ2IL9snehPNls0iXa5up4= -gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc42/go.mod h1:MLAmjPsXan0TixWBOnF2GUTjHcNLoAiYv1x1LRx7gHQ= +gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc43 h1:yHDCgmgeCC+R1F40HleRpPSPe3MVCmS8okvolxZ1Ack= +gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc43/go.mod h1:MLAmjPsXan0TixWBOnF2GUTjHcNLoAiYv1x1LRx7gHQ= gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE= gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE= gitlab.com/gitlab-org/labkit v1.17.0 h1:mEkoLzXorLNdt8NkfgYS5xMDhdqCsIJaeEVtSf7d8cU= -- cgit v1.2.3