summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-28 21:13:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-28 21:13:35 +0000
commit86ad1426d8a8f5d7f20bc5d8b536d3034d829d1f (patch)
tree7159021dd6fd3834a21096901bddb3b1915caa23
parent36eff6e5089629619cc55f4771fa949d6ae2b29b (diff)
downloadgitlab-ce-86ad1426d8a8f5d7f20bc5d8b536d3034d829d1f.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/line_length.yml1
-rw-r--r--.rubocop_todo/rspec/context_wording.yml1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum11
-rw-r--r--Gemfile.lock26
-rw-r--r--app/assets/javascripts/diffs/components/app.vue10
-rw-r--r--app/assets/javascripts/diffs/store/actions.js24
-rw-r--r--app/assets/javascripts/diffs/workers/tree_worker.js19
-rw-r--r--app/controllers/projects/issues_controller.rb10
-rw-r--r--app/graphql/types/root_storage_statistics_type.rb1
-rw-r--r--app/models/ci/daily_build_group_report_result.rb2
-rw-r--r--app/models/preloaders/user_max_access_level_in_groups_preloader.rb12
-rw-r--r--app/models/project.rb12
-rw-r--r--app/services/import/github/cancel_project_import_service.rb6
-rw-r--r--config/feature_flags/development/include_memberships_from_group_shares_in_preloader.yml8
-rw-r--r--db/migrate/20230222153048_add_registry_size_estimated_to_namespace_root_storage_statistics.rb21
-rw-r--r--db/migrate/20230224130315_add_constraint_type_to_postgres_async_constraint_validation.rb7
-rw-r--r--db/post_migrate/20230118144623_schedule_migration_for_remediation.rb25
-rw-r--r--db/post_migrate/20230125195503_queue_backfill_compliance_violations.rb24
-rw-r--r--db/schema_migrations/202301181446231
-rw-r--r--db/schema_migrations/202301251955031
-rw-r--r--db/schema_migrations/202302221530481
-rw-r--r--db/schema_migrations/202302241303151
-rw-r--r--db/structure.sql6
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/development/snowplow/event_dictionary_guide.md3
-rw-r--r--doc/integration/glab/index.md31
-rw-r--r--doc/user/project/repository/tags/img/tag-display_v15_9.pngbin0 -> 7320 bytes
-rw-r--r--doc/user/project/repository/tags/index.md21
-rw-r--r--lib/generators/gitlab/snowplow_event_definition_generator.rb9
-rw-r--r--lib/gitlab/background_migration/backfill_compliance_violations.rb17
-rw-r--r--lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb164
-rw-r--r--lib/gitlab/ci/pipeline/duration.rb1
-rw-r--r--lib/gitlab/database/async_constraints.rb2
-rw-r--r--lib/gitlab/database/async_constraints/migration_helpers.rb2
-rw-r--r--lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb3
-rw-r--r--lib/gitlab/import/import_failure_service.rb9
-rw-r--r--lib/gitlab/import/metrics.rb13
-rw-r--r--lib/sidebars/projects/menus/deployments_menu.rb9
-rw-r--r--lib/sidebars/projects/menus/infrastructure_menu.rb8
-rw-r--r--lib/sidebars/projects/menus/packages_registries_menu.rb9
-rw-r--r--lib/sidebars/projects/menus/snippets_menu.rb8
-rw-r--r--lib/sidebars/projects/super_sidebar_menus/operations_menu.rb19
-rw-r--r--lib/sidebars/projects/super_sidebar_panel.rb5
-rw-r--r--qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb5
-rw-r--r--spec/frontend/diffs/components/app_spec.js19
-rw-r--r--spec/frontend/diffs/store/actions_spec.js18
-rw-r--r--spec/graphql/types/root_storage_statistics_type_spec.rb2
-rw-r--r--spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb24
-rw-r--r--spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb161
-rw-r--r--spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb57
-rw-r--r--spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb18
-rw-r--r--spec/lib/gitlab/import/import_failure_service_spec.rb1
-rw-r--r--spec/lib/gitlab/import/metrics_spec.rb62
-rw-r--r--spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb12
-rw-r--r--spec/lib/sidebars/projects/super_sidebar_panel_spec.rb6
-rw-r--r--spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb31
-rw-r--r--spec/migrations/20230125195503_queue_backfill_compliance_violations_spec.rb32
-rw-r--r--spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb16
-rw-r--r--spec/models/project_spec.rb38
-rw-r--r--spec/requests/projects/issues_controller_spec.rb5
-rw-r--r--spec/services/import/github/cancel_project_import_service_spec.rb12
-rw-r--r--workhorse/go.mod2
-rw-r--r--workhorse/go.sum4
64 files changed, 902 insertions, 189 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 30c47ed2ed0..5508542a599 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -4034,7 +4034,6 @@ Layout/LineLength:
- 'spec/lib/error_tracking/sentry_client/projects_spec.rb'
- 'spec/lib/event_filter_spec.rb'
- 'spec/lib/feature_spec.rb'
- - 'spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb'
- 'spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb'
- 'spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb'
- 'spec/lib/generators/gitlab/usage_metric_generator_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index cb732ea307c..1ad85791e69 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -1636,7 +1636,6 @@ RSpec/ContextWording:
- 'spec/lib/extracts_ref_spec.rb'
- 'spec/lib/feature/definition_spec.rb'
- 'spec/lib/feature_spec.rb'
- - 'spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb'
- 'spec/lib/gitlab/alert_management/fingerprint_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
diff --git a/Gemfile b/Gemfile
index 5f12365e395..6de3d4a43a9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -566,7 +566,7 @@ gem 'oj-introspect', '~> 0.7'
gem 'multi_json', '~> 1.14.1'
gem 'yajl-ruby', '~> 1.4.3', require: 'yajl'
-gem 'webauthn', '~> 2.3'
+gem 'webauthn', '~> 3.0'
# IPAddress utilities
gem 'ipaddress', '~> 0.8.3'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 592d11baac2..2545eb99a5e 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -33,7 +33,7 @@
{"name":"attr_required","version":"1.0.1","platform":"ruby","checksum":"024e10393bd30901e1adf6769bd756b873a5ef7da60f86f8f11066116b5742bc"},
{"name":"autoprefixer-rails","version":"10.2.5.1","platform":"ruby","checksum":"3711d67f1112361c7628847ac192d8aa6f3b8abe47527aee8a69dc8985e798ee"},
{"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"},
-{"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"},
+{"name":"awrence","version":"1.2.1","platform":"ruby","checksum":"dd1d214c12a91f449d1ef81d7ee3babc2816944e450752e7522c65521872483e"},
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
{"name":"aws-partitions","version":"1.703.0","platform":"ruby","checksum":"3d32fcdcb2799fe0472a9b30990035713d7a75ac8b77bd7767ef5ee2914ea748"},
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
@@ -85,7 +85,7 @@
{"name":"concurrent-ruby","version":"1.2.0","platform":"ruby","checksum":"a5e799f71e7490f24a534d58c91380267d0ae306af0cdc518d6848b93475dae2"},
{"name":"connection_pool","version":"2.3.0","platform":"ruby","checksum":"677985be912f33c90f98f229aaa0c0ddb2ef8776f21929a36eeeb25251c944da"},
{"name":"cork","version":"0.3.0","platform":"ruby","checksum":"a0a0ac50e262f8514d1abe0a14e95e71c98b24e3378690e5d044daf0013ad4bc"},
-{"name":"cose","version":"1.0.0","platform":"ruby","checksum":"520ebaad97b56d2873de02ff4e2c973f5e77ce2f8edbda454af9ee3073643bc0"},
+{"name":"cose","version":"1.3.0","platform":"ruby","checksum":"63247c66a5bc76e53926756574fe3724cc0a88707e358c90532ae2a320e98601"},
{"name":"countries","version":"4.0.1","platform":"ruby","checksum":"d32e8a3c0b22949f1a41ea6d9005f5168ffce226f8fe077d1d6be785fffa81c5"},
{"name":"crack","version":"0.4.3","platform":"ruby","checksum":"5318ba8cd9cf7e0b5feb38948048503ba4b1fdc1b6ff30a39f0a00feb6036b29"},
{"name":"crass","version":"1.0.6","platform":"ruby","checksum":"dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d"},
@@ -406,7 +406,7 @@
{"name":"open4","version":"1.3.4","platform":"ruby","checksum":"a1df037310624ecc1ea1d81264b11c83e96d0c3c1c6043108d37d396dcd0f4b1"},
{"name":"openid_connect","version":"1.3.0","platform":"ruby","checksum":"a796855096850cc01140e37ea6ae9fd14f2be818b9b5bc698418063dfe228770"},
{"name":"openssl","version":"2.2.2","platform":"ruby","checksum":"53f72382bac046c36c37049c7ec9d5597d42628d140b5cfbcd61e0226c0ca077"},
-{"name":"openssl-signature_algorithm","version":"0.4.0","platform":"ruby","checksum":"e53a225b773784935249cf4c61238c6cf0e1e464e78ae2f8ddaf995fb22ca991"},
+{"name":"openssl-signature_algorithm","version":"1.3.0","platform":"ruby","checksum":"a3b40b5e8276162d4a6e50c7c97cdaf1446f9b2c3946a6fa2c14628e0c957e80"},
{"name":"opentracing","version":"0.5.0","platform":"ruby","checksum":"deb5d7abe6b0e7631d866d8cb5ee7bb9352650a504a32f61591302bc510b9286"},
{"name":"optimist","version":"3.0.1","platform":"ruby","checksum":"336b753676d6117cad9301fac7e91dab4228f747d4e7179891ad3a163c64e2ed"},
{"name":"org-ruby","version":"0.9.12","platform":"ruby","checksum":"93cbec3a4470cb9dca6a4a98dc276a6434ea9d9e7bc2d42ea33c3aedd5d1c974"},
@@ -534,7 +534,6 @@
{"name":"sassc-rails","version":"2.1.0","platform":"ruby","checksum":"764dcc74e06930e3483caf0d595084d11f2b0fefd6539abf487cdddfba6cafa2"},
{"name":"sawyer","version":"0.9.2","platform":"ruby","checksum":"fa3a72d62a4525517b18857ddb78926aab3424de0129be6772a8e2ba240e7aca"},
{"name":"sd_notify","version":"0.1.1","platform":"ruby","checksum":"cbc7ac6caa7cedd26b30a72b5eeb6f36050dc0752df263452ea24fb5a4ad3131"},
-{"name":"securecompare","version":"1.0.0","platform":"ruby","checksum":"cb0c6599deaaedf6d28f8d88538b06e7198c4826b1b8edb1dbeb44a2162fc62b"},
{"name":"seed-fu","version":"2.3.7","platform":"ruby","checksum":"f19673443e9af799b730e3d4eca6a89b39e5a36825015dffd00d02ea3365cf74"},
{"name":"selenium-webdriver","version":"3.142.7","platform":"ruby","checksum":"dea0993e0e4fdb364f0453144814c0e6099a411d17396807c6cac666d0ddac29"},
{"name":"sentry-rails","version":"5.1.1","platform":"ruby","checksum":"906ef0a776ddc35884ab8b548856ba81c607e3fdee7c9c9f7c44efccc16a657f"},
@@ -609,7 +608,7 @@
{"name":"tins","version":"1.31.1","platform":"ruby","checksum":"51c4a347c25c630d310cbc2c040ffb84e266c8227f2ade881f1130ee4f9fbecf"},
{"name":"toml-rb","version":"2.2.0","platform":"ruby","checksum":"a1e2c54ac3cc9d49861004f75f0648b3622ac03a76abe105358c31553227d9a6"},
{"name":"tomlrb","version":"1.3.0","platform":"ruby","checksum":"68666bf53fa70ba686a48a7435ce7e086f5227c58c4c993bd9792f4760f2a503"},
-{"name":"tpm-key_attestation","version":"0.9.0","platform":"ruby","checksum":"e469ad9111a68dab4d04596e1c0621d7c877c2e3e247f765af3c04f1adf2b8cd"},
+{"name":"tpm-key_attestation","version":"0.12.0","platform":"ruby","checksum":"e133d80cf24fef0e7a7dfad00fd6aeff01fc79875fbfc66cd8537bbd622b1e6d"},
{"name":"trailblazer-option","version":"0.1.2","platform":"ruby","checksum":"20e4f12ea4e1f718c8007e7944ca21a329eee4eed9e0fa5dde6e8ad8ac4344a3"},
{"name":"train-core","version":"3.4.9","platform":"ruby","checksum":"d7ad8fa9a379c43a30baaaf1141af1cb28349d386c054f7fc81d169a625d6edd"},
{"name":"truncato","version":"0.7.12","platform":"ruby","checksum":"fed9e8a04fa35fd1a64506cd2089761bae4adfe47e756c3ce98a5c43856c9c4c"},
@@ -646,7 +645,7 @@
{"name":"vmstat","version":"2.3.0","platform":"ruby","checksum":"ab5446a3e3bd0a9cdb9d9ac69a0bbd119c4f161d945a0846a519dd7018af656d"},
{"name":"warden","version":"1.2.9","platform":"ruby","checksum":"46684f885d35a69dbb883deabf85a222c8e427a957804719e143005df7a1efd0"},
{"name":"warning","version":"1.3.0","platform":"ruby","checksum":"23695a5d8e50bd5c46068931b529bee0b28e4982cbcefbe77d867800dde8069e"},
-{"name":"webauthn","version":"2.3.0","platform":"ruby","checksum":"96fbee59f4a45219f1dae96f467b693de144f871be9ec6ea357168624dacd89e"},
+{"name":"webauthn","version":"3.0.0","platform":"ruby","checksum":"3f77d422c2a8a4b31e56cf42f83414bd066e0506e9896936e1730262dc4a20e6"},
{"name":"webfinger","version":"1.2.0","platform":"ruby","checksum":"7814ef1c85da47514f65c6e5ca14205fa9ce41ea2a70785e0c872842162852a2"},
{"name":"webmock","version":"3.9.1","platform":"ruby","checksum":"bcf6822456b234fb1bed2b0a89bff31fe0641214b44f6ba4ced2b824cf31337d"},
{"name":"webrick","version":"1.6.1","platform":"ruby","checksum":"0b4d1eab918f5f53333c690ad470825e51844ce9851e403a3fd47d6a84d9d67c"},
diff --git a/Gemfile.lock b/Gemfile.lock
index c8c2c775198..d64be58596b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -198,7 +198,7 @@ GEM
autoprefixer-rails (10.2.5.1)
execjs (> 0)
awesome_print (1.9.2)
- awrence (1.1.1)
+ awrence (1.2.1)
aws-eventstream (1.2.0)
aws-partitions (1.703.0)
aws-sdk-cloudformation (1.41.0)
@@ -298,9 +298,9 @@ GEM
connection_pool (2.3.0)
cork (0.3.0)
colored2 (~> 3.1)
- cose (1.0.0)
+ cose (1.3.0)
cbor (~> 0.5.9)
- openssl-signature_algorithm (~> 0.4.0)
+ openssl-signature_algorithm (~> 1.0)
countries (4.0.1)
i18n_data (~> 0.13.0)
sixarm_ruby_unaccent (~> 1.1)
@@ -1041,7 +1041,8 @@ GEM
webfinger (>= 1.0.1)
openssl (2.2.2)
ipaddr
- openssl-signature_algorithm (0.4.0)
+ openssl-signature_algorithm (1.3.0)
+ openssl (> 2.0)
opentracing (0.5.0)
optimist (3.0.1)
org-ruby (0.9.12)
@@ -1335,7 +1336,6 @@ GEM
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
sd_notify (0.1.1)
- securecompare (1.0.0)
seed-fu (2.3.7)
activerecord (>= 3.1)
activesupport (>= 3.1)
@@ -1472,9 +1472,10 @@ GEM
toml-rb (2.2.0)
citrus (~> 3.0, > 3.0)
tomlrb (1.3.0)
- tpm-key_attestation (0.9.0)
+ tpm-key_attestation (0.12.0)
bindata (~> 2.4)
- openssl-signature_algorithm (~> 0.4.0)
+ openssl (> 2.0)
+ openssl-signature_algorithm (~> 1.0)
trailblazer-option (0.1.2)
train-core (3.4.9)
addressable (~> 2.5)
@@ -1547,16 +1548,15 @@ GEM
warden (1.2.9)
rack (>= 2.0.9)
warning (1.3.0)
- webauthn (2.3.0)
+ webauthn (3.0.0)
android_key_attestation (~> 0.3.0)
awrence (~> 1.1)
bindata (~> 2.4)
cbor (~> 0.5.9)
- cose (~> 1.0)
- openssl (~> 2.0)
+ cose (~> 1.1)
+ openssl (>= 2.2)
safety_net_attestation (~> 0.4.0)
- securecompare (~> 1.0)
- tpm-key_attestation (~> 0.9.0)
+ tpm-key_attestation (~> 0.12.0)
webfinger (1.2.0)
activesupport
httpclient (>= 2.4)
@@ -1886,7 +1886,7 @@ DEPENDENCIES
view_component (~> 2.74.1)
vmstat (~> 2.3.0)
warning (~> 1.3.0)
- webauthn (~> 2.3)
+ webauthn (~> 3.0)
webmock (~> 3.9.1)
webrick (~> 1.6.1)
wikicloth (= 0.8.1)
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 35d1a564178..c8ba4a1676d 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -21,6 +21,7 @@ import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '~/notes/event_hub';
+import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
@@ -53,15 +54,14 @@ import HiddenFilesWarning from './hidden_files_warning.vue';
import NoChanges from './no_changes.vue';
import TreeList from './tree_list.vue';
import VirtualScrollerScrollSync from './virtual_scroller_scroll_sync';
+import PreRenderer from './pre_renderer.vue';
export default {
name: 'DiffsApp',
components: {
- DynamicScroller: () =>
- import('vendor/vue-virtual-scroller').then(({ DynamicScroller }) => DynamicScroller),
- DynamicScrollerItem: () =>
- import('vendor/vue-virtual-scroller').then(({ DynamicScrollerItem }) => DynamicScrollerItem),
- PreRenderer: () => import('./pre_renderer.vue').then((PreRenderer) => PreRenderer),
+ DynamicScroller,
+ DynamicScrollerItem,
+ PreRenderer,
VirtualScrollerScrollSync,
CompareVersions,
DiffFile,
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 9f90de9abde..9d7a540570e 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -14,6 +14,8 @@ import Poll from '~/lib/utils/poll';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import notesEventHub from '~/notes/event_hub';
+import { generateTreeList } from '~/diffs/utils/tree_worker_utils';
+import { sortTree } from '~/ide/stores/utils';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
@@ -52,7 +54,6 @@ import { isCollapsed } from '../utils/diff_file';
import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews';
import { getDerivedMergeRequestInformation } from '../utils/merge_request';
import { queueRedisHllEvents } from '../utils/queue_events';
-import TreeWorker from '../workers/tree_worker?worker';
import * as types from './mutation_types';
import {
getDiffPositionByLineCode,
@@ -199,21 +200,12 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
};
export const fetchDiffFilesMeta = ({ commit, state }) => {
- const worker = new TreeWorker();
const urlParams = {
view: 'inline',
w: state.showWhitespace ? '0' : '1',
};
commit(types.SET_LOADING, true);
- eventHub.$emit(EVT_PERF_MARK_FILE_TREE_START);
-
- worker.addEventListener('message', ({ data }) => {
- commit(types.SET_TREE_DATA, data);
- eventHub.$emit(EVT_PERF_MARK_FILE_TREE_END);
-
- worker.terminate();
- });
return axios
.get(mergeUrlParams(urlParams, state.endpointMetadata))
@@ -225,18 +217,24 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
commit(types.SET_MERGE_REQUEST_DIFFS, data.merge_request_diffs || []);
commit(types.SET_DIFF_METADATA, strippedData);
- worker.postMessage(data.diff_files);
+ eventHub.$emit(EVT_PERF_MARK_FILE_TREE_START);
+ const { treeEntries, tree } = generateTreeList(data.diff_files);
+ eventHub.$emit(EVT_PERF_MARK_FILE_TREE_END);
+ commit(types.SET_TREE_DATA, {
+ treeEntries,
+ tree: sortTree(tree),
+ });
return data;
})
.catch((error) => {
- worker.terminate();
-
if (error.response.status === HTTP_STATUS_NOT_FOUND) {
createAlert({
message: __('Building your merge request. Wait a few moments, then refresh this page.'),
variant: VARIANT_WARNING,
});
+ } else {
+ throw error;
}
});
};
diff --git a/app/assets/javascripts/diffs/workers/tree_worker.js b/app/assets/javascripts/diffs/workers/tree_worker.js
deleted file mode 100644
index 04010a99b52..00000000000
--- a/app/assets/javascripts/diffs/workers/tree_worker.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { sortTree } from '~/ide/stores/utils';
-import { generateTreeList } from '../utils/tree_worker_utils';
-
-// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', (e) => {
- const { data } = e;
-
- if (data === undefined) {
- return;
- }
-
- const { treeEntries, tree } = generateTreeList(data);
-
- // eslint-disable-next-line no-restricted-globals
- self.postMessage({
- treeEntries,
- tree: sortTree(tree),
- });
-});
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 21227d62023..37b76257128 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -21,6 +21,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :check_issues_available!
before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
before_action :redirect_if_work_item, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
+ before_action :require_incident_for_incident_routes, only: :show
after_action :log_issue_show, only: :show
@@ -449,6 +450,15 @@ class Projects::IssuesController < Projects::ApplicationController
redirect_to project_work_items_path(project, issue.id, params: request.query_parameters)
end
end
+
+ def require_incident_for_incident_routes
+ return unless params[:incident_tab].present?
+ return if issue.incident?
+
+ # Redirect instead of 404 to gracefully handle
+ # issue type changes
+ redirect_to project_issue_path(project, issue)
+ end
end
Projects::IssuesController.prepend_mod_with('Projects::IssuesController')
diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb
index 64aaf3e73a0..67ee0589882 100644
--- a/app/graphql/types/root_storage_statistics_type.rb
+++ b/app/graphql/types/root_storage_statistics_type.rb
@@ -12,6 +12,7 @@ module Types
field :lfs_objects_size, GraphQL::Types::Float, null: false, description: 'LFS objects size in bytes.'
field :packages_size, GraphQL::Types::Float, null: false, description: 'Packages size in bytes.'
field :pipeline_artifacts_size, GraphQL::Types::Float, null: false, description: 'CI pipeline artifacts size in bytes.'
+ field :registry_size_estimated, GraphQL::Types::Boolean, null: false, description: 'Indicates whether the deduplicated Container Registry size for the namespace is an estimated value or not.'
field :repository_size, GraphQL::Types::Float, null: false, description: 'Git repository size in bytes.'
field :snippets_size, GraphQL::Types::Float, null: false, description: 'Snippets size in bytes.'
field :storage_size, GraphQL::Types::Float, null: false, description: 'Total storage in bytes.'
diff --git a/app/models/ci/daily_build_group_report_result.rb b/app/models/ci/daily_build_group_report_result.rb
index 598d1456a48..ffb29b48f99 100644
--- a/app/models/ci/daily_build_group_report_result.rb
+++ b/app/models/ci/daily_build_group_report_result.rb
@@ -6,7 +6,7 @@ module Ci
belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id
belongs_to :project
- belongs_to :group
+ belongs_to :group, class_name: '::Group'
validates :data, json_schema: { filename: "daily_build_group_report_result_data" }
diff --git a/app/models/preloaders/user_max_access_level_in_groups_preloader.rb b/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
index 0c747ad9c84..16d46facb96 100644
--- a/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
+++ b/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
@@ -46,14 +46,10 @@ module Preloaders
end
def all_memberships
- if Feature.enabled?(:include_memberships_from_group_shares_in_preloader)
- [
- direct_memberships.select(*GroupMember.cached_column_list),
- memberships_from_group_shares
- ]
- else
- [direct_memberships]
- end
+ [
+ direct_memberships.select(*GroupMember.cached_column_list),
+ memberships_from_group_shares
+ ]
end
def direct_memberships
diff --git a/app/models/project.rb b/app/models/project.rb
index 96e3a9e0f8f..ae4cedb5af3 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1272,6 +1272,18 @@ class Project < ApplicationRecord
import_state&.human_status_name || 'none'
end
+ def beautified_import_status_name
+ if import_finished?
+ return 'completed' unless import_checksums.present?
+
+ fetched = import_checksums['fetched']
+ imported = import_checksums['imported']
+ fetched.keys.any? { |key| fetched[key] != imported[key] } ? 'partially completed' : 'completed'
+ else
+ import_status
+ end
+ end
+
def add_import_job
job_id =
if forked?
diff --git a/app/services/import/github/cancel_project_import_service.rb b/app/services/import/github/cancel_project_import_service.rb
index 5dce5e73662..616ae54451f 100644
--- a/app/services/import/github/cancel_project_import_service.rb
+++ b/app/services/import/github/cancel_project_import_service.rb
@@ -9,6 +9,8 @@ module Import
if project.import_in_progress?
project.import_state.cancel
+ metrics.track_import_state
+
success(project: project)
else
error(cannot_cancel_error_message, :bad_request)
@@ -31,6 +33,10 @@ module Import
project_status: project.import_state.status
)
end
+
+ def metrics
+ @metrics ||= Gitlab::Import::Metrics.new(:github_importer, project)
+ end
end
end
end
diff --git a/config/feature_flags/development/include_memberships_from_group_shares_in_preloader.yml b/config/feature_flags/development/include_memberships_from_group_shares_in_preloader.yml
deleted file mode 100644
index d7f2d1f5552..00000000000
--- a/config/feature_flags/development/include_memberships_from_group_shares_in_preloader.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: include_memberships_from_group_shares_in_preloader
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111157
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/390780
-milestone: '15.9'
-type: development
-group: group::organization
-default_enabled: false
diff --git a/db/migrate/20230222153048_add_registry_size_estimated_to_namespace_root_storage_statistics.rb b/db/migrate/20230222153048_add_registry_size_estimated_to_namespace_root_storage_statistics.rb
new file mode 100644
index 00000000000..50fcf6fd113
--- /dev/null
+++ b/db/migrate/20230222153048_add_registry_size_estimated_to_namespace_root_storage_statistics.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddRegistrySizeEstimatedToNamespaceRootStorageStatistics < Gitlab::Database::Migration[2.1]
+ INDEX_NAME = 'index_ns_root_stor_stats_on_registry_size_estimated'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :namespace_root_storage_statistics, :registry_size_estimated, :boolean, default: false, null: false
+ end
+
+ add_concurrent_index :namespace_root_storage_statistics, :registry_size_estimated, name: INDEX_NAME
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespace_root_storage_statistics, :registry_size_estimated
+ end
+ end
+end
diff --git a/db/migrate/20230224130315_add_constraint_type_to_postgres_async_constraint_validation.rb b/db/migrate/20230224130315_add_constraint_type_to_postgres_async_constraint_validation.rb
new file mode 100644
index 00000000000..dee5810d0d1
--- /dev/null
+++ b/db/migrate/20230224130315_add_constraint_type_to_postgres_async_constraint_validation.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddConstraintTypeToPostgresAsyncConstraintValidation < Gitlab::Database::Migration[2.1]
+ def change
+ add_column :postgres_async_foreign_key_validations, :constraint_type, :integer, null: false, default: 0, limit: 2
+ end
+end
diff --git a/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb b/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb
new file mode 100644
index 00000000000..af9b7d65a55
--- /dev/null
+++ b/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ScheduleMigrationForRemediation < Gitlab::Database::Migration[2.1]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = 'MigrateRemediationsForVulnerabilityFindings'
+ DELAY_INTERVAL = 2.minutes
+ SUB_BATCH_SIZE = 500
+ BATCH_SIZE = 5000
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :vulnerability_occurrences,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
+ end
+end
diff --git a/db/post_migrate/20230125195503_queue_backfill_compliance_violations.rb b/db/post_migrate/20230125195503_queue_backfill_compliance_violations.rb
new file mode 100644
index 00000000000..5f797421bd5
--- /dev/null
+++ b/db/post_migrate/20230125195503_queue_backfill_compliance_violations.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class QueueBackfillComplianceViolations < Gitlab::Database::Migration[2.1]
+ MIGRATION = 'BackfillComplianceViolations'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 10_000
+
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :merge_requests_compliance_violations,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :merge_requests_compliance_violations, :id, [])
+ end
+end
diff --git a/db/schema_migrations/20230118144623 b/db/schema_migrations/20230118144623
new file mode 100644
index 00000000000..82c15116c45
--- /dev/null
+++ b/db/schema_migrations/20230118144623
@@ -0,0 +1 @@
+3ceeeeabb4ebae0f38e446c044fe6e6d929661b8689b461bed87660afd2e223b \ No newline at end of file
diff --git a/db/schema_migrations/20230125195503 b/db/schema_migrations/20230125195503
new file mode 100644
index 00000000000..ee8f7d47e16
--- /dev/null
+++ b/db/schema_migrations/20230125195503
@@ -0,0 +1 @@
+6321659d8f71127368dffd0bec122d4c32835da364a32cd6f276c641a70d10ff \ No newline at end of file
diff --git a/db/schema_migrations/20230222153048 b/db/schema_migrations/20230222153048
new file mode 100644
index 00000000000..66347d3252f
--- /dev/null
+++ b/db/schema_migrations/20230222153048
@@ -0,0 +1 @@
+ff11462b7e827b0ae66f54b131fa0d4099a6e7cc768fc9b400ee36346d1773fa \ No newline at end of file
diff --git a/db/schema_migrations/20230224130315 b/db/schema_migrations/20230224130315
new file mode 100644
index 00000000000..44960762a62
--- /dev/null
+++ b/db/schema_migrations/20230224130315
@@ -0,0 +1 @@
+e54ddd26174440b453482d4c3d2dd8aa8cacbb2697162d9f976ed52a0d55f1a0 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 96f828f7453..78adedc12eb 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -18533,7 +18533,8 @@ CREATE TABLE namespace_root_storage_statistics (
uploads_size bigint DEFAULT 0 NOT NULL,
dependency_proxy_size bigint DEFAULT 0 NOT NULL,
notification_level smallint DEFAULT 100 NOT NULL,
- container_registry_size bigint DEFAULT 0 NOT NULL
+ container_registry_size bigint DEFAULT 0 NOT NULL,
+ registry_size_estimated boolean DEFAULT false NOT NULL
);
CREATE TABLE namespace_settings (
@@ -20063,6 +20064,7 @@ CREATE TABLE postgres_async_foreign_key_validations (
table_name text NOT NULL,
last_error text,
attempts integer DEFAULT 0 NOT NULL,
+ constraint_type smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_536a40afbf CHECK ((char_length(last_error) <= 10000)),
CONSTRAINT check_74fb7c8e57 CHECK ((char_length(name) <= 63)),
CONSTRAINT check_cd435d6301 CHECK ((char_length(table_name) <= 63))
@@ -31010,6 +31012,8 @@ CREATE INDEX index_notification_settings_on_source_and_level_and_user ON notific
CREATE UNIQUE INDEX index_notifications_on_user_id_and_source_id_and_source_type ON notification_settings USING btree (user_id, source_id, source_type);
+CREATE INDEX index_ns_root_stor_stats_on_registry_size_estimated ON namespace_root_storage_statistics USING btree (registry_size_estimated);
+
CREATE UNIQUE INDEX index_ns_user_callouts_feature ON user_namespace_callouts USING btree (user_id, feature_name, namespace_id);
CREATE INDEX index_oauth_access_grants_on_resource_owner_id ON oauth_access_grants USING btree (resource_owner_id, application_id, created_at);
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 2cc8ebf3897..d27c158e3e7 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -19914,6 +19914,7 @@ Counts of requirements by their state.
| <a id="rootstoragestatisticslfsobjectssize"></a>`lfsObjectsSize` | [`Float!`](#float) | LFS objects size in bytes. |
| <a id="rootstoragestatisticspackagessize"></a>`packagesSize` | [`Float!`](#float) | Packages size in bytes. |
| <a id="rootstoragestatisticspipelineartifactssize"></a>`pipelineArtifactsSize` | [`Float!`](#float) | CI pipeline artifacts size in bytes. |
+| <a id="rootstoragestatisticsregistrysizeestimated"></a>`registrySizeEstimated` | [`Boolean!`](#boolean) | Indicates whether the deduplicated Container Registry size for the namespace is an estimated value or not. |
| <a id="rootstoragestatisticsrepositorysize"></a>`repositorySize` | [`Float!`](#float) | Git repository size in bytes. |
| <a id="rootstoragestatisticssnippetssize"></a>`snippetsSize` | [`Float!`](#float) | Snippets size in bytes. |
| <a id="rootstoragestatisticsstoragesize"></a>`storageSize` | [`Float!`](#float) | Total storage in bytes. |
diff --git a/doc/development/snowplow/event_dictionary_guide.md b/doc/development/snowplow/event_dictionary_guide.md
index 487e3e393d2..dc2214a40ed 100644
--- a/doc/development/snowplow/event_dictionary_guide.md
+++ b/doc/development/snowplow/event_dictionary_guide.md
@@ -79,14 +79,13 @@ tiers:
Use the dedicated [event definition generator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/generators/gitlab/snowplow_event_definition_generator.rb)
to create new event definitions.
-The `category` and `action` of each event are included in the filename to enforce uniqueness.
+The `category` and `action` of each event are included in the filename to standardize file naming.
The generator takes three options:
- `--ee`: Indicates if the event is for EE.
- `--category=CATEGORY`: Indicates the `category` of the event.
- `--action=ACTION`: Indicates the `action` of the event.
-- `--force`: Overwrites the existing event definition, if one already exists.
```shell
bundle exec rails generate gitlab:snowplow_event_definition --category Groups::EmailCampaignsController --action click
diff --git a/doc/integration/glab/index.md b/doc/integration/glab/index.md
index 621472a2083..3e143b9f8c2 100644
--- a/doc/integration/glab/index.md
+++ b/doc/integration/glab/index.md
@@ -43,19 +43,24 @@ glab mr merge
## Core commands
-- `glab alias`
-- `glab api`
-- `glab auth`
-- `glab ci`
-- `glab issue`
-- `glab label`
-- `glab mr`
-- `glab project`
-- `glab release`
-- `glab snippet`
-- `glab ssh-key`
-- `glab user`
-- `glab variable`
+- [`glab alias`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/alias)
+- [`glab api`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/api)
+- [`glab auth`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/auth)
+- [`glab check-update`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/check-update)
+- [`glab ci`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/ci)
+- [`glab completion`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/completion)
+- [`glab config`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/config)
+- [`glab incident`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/incident)
+- [`glab issue`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/ci)
+- [`glab label`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/label)
+- [`glab mr`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/mr)
+- [`glab release`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/release)
+- [`glab repo`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/repo)
+- [`glab schedule`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/schedule)
+- [`glab snippet`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/snippet)
+- [`glab ssh-key`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/ssh-key)
+- [`glab user`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/user)
+- [`glab variable`](https://gitlab.com/gitlab-org/cli/-/tree/main/docs/source/variable)
## Install the CLI
diff --git a/doc/user/project/repository/tags/img/tag-display_v15_9.png b/doc/user/project/repository/tags/img/tag-display_v15_9.png
new file mode 100644
index 00000000000..015df07d025
--- /dev/null
+++ b/doc/user/project/repository/tags/img/tag-display_v15_9.png
Binary files differ
diff --git a/doc/user/project/repository/tags/index.md b/doc/user/project/repository/tags/index.md
index d12a4e9f2e4..3d340789c2c 100644
--- a/doc/user/project/repository/tags/index.md
+++ b/doc/user/project/repository/tags/index.md
@@ -15,6 +15,25 @@ reference. Git supports two types of tags:
Many projects combine an annotated release tag with a stable branch. Consider
setting deployment or release tags automatically.
+## View tags for a project
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Repository > Tags**.
+
+![Example of a single tag](img/tag-display_v15_9.png)
+
+In the GitLab UI, each tag displays:
+
+- The tag name. (**{tag}**)
+- Optional. If the tag is [protected](../../protected_tags.md), a **protected** badge.
+- The commit SHA (**{commit}**), linked to the commit's contents.
+- The commit's title and creation date.
+- Optional. A link to the release (**{rocket}**).
+- Optional. If a pipeline has been run, the current pipeline status.
+- Download links to the source code and artifacts linked to the tag.
+- A [**Create release**](../../releases/index.md#create-a-release) (**{pencil}**) link.
+- A link to delete the tag.
+
## Tags sample workflow
1. Create a lightweight tag.
@@ -22,7 +41,7 @@ setting deployment or release tags automatically.
1. Push the tags to the remote repository.
```shell
-git checkout master
+git checkout main
# Lightweight tag
git tag my_lightweight_tag
diff --git a/lib/generators/gitlab/snowplow_event_definition_generator.rb b/lib/generators/gitlab/snowplow_event_definition_generator.rb
index 827e87dc313..8baeb6ba8c7 100644
--- a/lib/generators/gitlab/snowplow_event_definition_generator.rb
+++ b/lib/generators/gitlab/snowplow_event_definition_generator.rb
@@ -14,12 +14,11 @@ module Gitlab
class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if event is for ee'
class_option :category, type: :string, optional: false, desc: 'Category of the event'
class_option :action, type: :string, optional: false, desc: 'Action of the event'
- class_option :force, type: :boolean, optional: true, default: false, desc: 'Overwrite existing definition'
def create_event_file
- raise "Event definition already exists at #{file_path}" if definition_exists? && !force_definition_override?
+ raise "Event definition already exists at #{file_path}" if definition_exists?
- template "event_definition.yml", file_path, force: force_definition_override?
+ template "event_definition.yml", file_path, force: false
end
def distributions
@@ -42,10 +41,6 @@ module Gitlab
options[:ee]
end
- def force_definition_override?
- options[:force]
- end
-
private
def definition_exists?
diff --git a/lib/gitlab/background_migration/backfill_compliance_violations.rb b/lib/gitlab/background_migration/backfill_compliance_violations.rb
new file mode 100644
index 00000000000..131b4a05e41
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_compliance_violations.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class BackfillComplianceViolations < Gitlab::BackgroundMigration::BatchedMigrationJob
+ feature_category :compliance_management
+
+ def perform
+ # no-op. The logic is defined in EE module.
+ end
+ end
+ # rubocop: enable Style/Documentation
+ end
+end
+
+::Gitlab::BackgroundMigration::BackfillComplianceViolations.prepend_mod
diff --git a/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb b/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb
new file mode 100644
index 00000000000..7a2f4dab742
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+module Vulnerabilities
+ # The class is mimicking Vulnerabilites::Remediation
+ class Remediation < ApplicationRecord
+ include FileStoreMounter
+ include ShaAttribute
+
+ self.table_name = 'vulnerability_remediations'
+
+ sha_attribute :checksum
+
+ mount_file_store_uploader AttachmentUploader
+
+ def retrieve_upload(_identifier, paths)
+ Upload.find_by(model: self, path: paths)
+ end
+ end
+end
+
+module Gitlab
+ module BackgroundMigration
+ # The class to migrate the remediation data into their own records from the json attribute
+ class MigrateRemediationsForVulnerabilityFindings < BatchedMigrationJob
+ feature_category :vulnerability_management
+ operation_name :migrate_remediations_for_vulnerability_findings
+
+ # The class to encapsulate checksum and file for uploading
+ class DiffFile < StringIO
+ # This method is used by the `carrierwave` gem
+ def original_filename
+ @original_filename ||= self.class.original_filename(checksum)
+ end
+
+ def checksum
+ @checksum ||= self.class.checksum(string)
+ end
+
+ def self.checksum(value)
+ Digest::SHA256.hexdigest(value)
+ end
+
+ def self.original_filename(checksum)
+ "#{checksum}.diff"
+ end
+ end
+
+ # The class is mimicking Vulnerabilites::Finding
+ class Finding < ApplicationRecord
+ self.table_name = 'vulnerability_occurrences'
+
+ validates :details, json_schema: { filename: 'vulnerability_finding_details', draft: 7 }, if: false
+ end
+
+ # The class is mimicking Vulnerabilites::FindingRemediation
+ class FindingRemediation < ApplicationRecord
+ self.table_name = 'vulnerability_findings_remediations'
+ end
+
+ def perform
+ each_sub_batch do |sub_batch|
+ migrate_remediations(sub_batch)
+ end
+ end
+
+ private
+
+ def migrate_remediations(sub_batch)
+ sub_batch.each do |finding|
+ FindingRemediation.transaction do
+ remediations = append_remediations_diff_checksum(finding.raw_metadata)
+
+ result_ids = create_remediations(finding, remediations)
+
+ create_finding_remediations(finding.id, result_ids)
+ end
+ rescue StandardError => e
+ logger.error(
+ message: e.message,
+ class: self.class.name,
+ model_id: finding.id
+ )
+ end
+ end
+
+ def create_finding_remediations(finding_id, result_ids)
+ attrs = result_ids.map do |result_id|
+ build_finding_remediation_attrs(finding_id, result_id)
+ end
+
+ return unless attrs.present?
+
+ FindingRemediation.upsert_all(
+ attrs,
+ returning: false,
+ unique_by: [:vulnerability_occurrence_id, :vulnerability_remediation_id]
+ )
+ end
+
+ def create_remediations(finding, remediations)
+ attrs = remediations.map do |remediation|
+ build_remediation_attrs(finding, remediation)
+ end
+
+ return [] unless attrs.present?
+
+ ids_checksums = ::Vulnerabilities::Remediation.upsert_all(
+ attrs,
+ returning: %w[id checksum],
+ unique_by: [:project_id, :checksum]
+ )
+
+ ids_checksums.each do |id_checksum|
+ upload_file(id_checksum['id'], id_checksum['checksum'], remediations)
+ end
+
+ ids_checksums.pluck('id')
+ end
+
+ def upload_file(id, checksum, remediations)
+ deserialized_checksum = Gitlab::Database::ShaAttribute.new.deserialize(checksum)
+ diff = remediations.find { |rem| rem['checksum'] == deserialized_checksum }["diff"]
+ file = DiffFile.new(diff)
+ ::Vulnerabilities::Remediation.find_by(id: id).update!(file: file)
+ end
+
+ def build_remediation_attrs(finding, remediation)
+ {
+ project_id: finding.project_id,
+ summary: remediation['summary'],
+ file: DiffFile.original_filename(remediation['checksum']),
+ checksum: remediation['checksum'],
+ created_at: Time.current,
+ updated_at: Time.current
+ }
+ end
+
+ def build_finding_remediation_attrs(finding_id, remediation_id)
+ {
+ vulnerability_occurrence_id: finding_id,
+ vulnerability_remediation_id: remediation_id,
+ created_at: Time.current,
+ updated_at: Time.current
+ }
+ end
+
+ def append_remediations_diff_checksum(metadata)
+ parsed_metadata = Gitlab::Json.parse(metadata)
+
+ return [] unless parsed_metadata['remediations']
+
+ parsed_metadata['remediations'].filter_map do |remediation|
+ next unless remediation
+
+ remediation.merge('checksum' => DiffFile.checksum(remediation['diff']))
+ end.compact.uniq
+ end
+
+ def logger
+ @logger ||= ::Gitlab::AppLogger
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/duration.rb b/lib/gitlab/ci/pipeline/duration.rb
index 15cc238fa84..11155280fdb 100644
--- a/lib/gitlab/ci/pipeline/duration.rb
+++ b/lib/gitlab/ci/pipeline/duration.rb
@@ -147,7 +147,6 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def self_and_downstreams_builds_of_pipeline(pipeline)
::Ci::Build
- .unscoped # Will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/391186
.select(:id, :type, :started_at, :finished_at)
.in_pipelines(
pipeline.self_and_downstreams.select(:id)
diff --git a/lib/gitlab/database/async_constraints.rb b/lib/gitlab/database/async_constraints.rb
index c4e05a88430..6952115eca5 100644
--- a/lib/gitlab/database/async_constraints.rb
+++ b/lib/gitlab/database/async_constraints.rb
@@ -6,7 +6,7 @@ module Gitlab
DEFAULT_ENTRIES_PER_INVOCATION = 2
def self.validate_pending_entries!(how_many: DEFAULT_ENTRIES_PER_INVOCATION)
- PostgresAsyncConstraintValidation.ordered.limit(how_many).each do |record|
+ PostgresAsyncConstraintValidation.ordered.foreign_key_type.limit(how_many).each do |record|
ForeignKeyValidator.new(record).perform
end
end
diff --git a/lib/gitlab/database/async_constraints/migration_helpers.rb b/lib/gitlab/database/async_constraints/migration_helpers.rb
index f51bb015c88..77ca78a4d5c 100644
--- a/lib/gitlab/database/async_constraints/migration_helpers.rb
+++ b/lib/gitlab/database/async_constraints/migration_helpers.rb
@@ -21,6 +21,7 @@ module Gitlab
end
async_validation = PostgresAsyncConstraintValidation
+ .foreign_key_type
.find_or_create_by!(name: fk_name, table_name: table_name)
Gitlab::AppLogger.info(
@@ -39,6 +40,7 @@ module Gitlab
fk_name = name || concurrent_foreign_key_name(table_name, column_name)
PostgresAsyncConstraintValidation
+ .foreign_key_type
.find_by(name: fk_name, table_name: table_name)
.try(&:destroy!)
end
diff --git a/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb b/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb
index ae996600f7c..3e71deb6855 100644
--- a/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb
+++ b/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb
@@ -14,7 +14,10 @@ module Gitlab
validates :name, presence: true, uniqueness: { scope: :table_name }, length: { maximum: MAX_IDENTIFIER_LENGTH }
validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH }
+ enum constraint_type: { foreign_key: 0 }
+
scope :ordered, -> { order(attempts: :asc, id: :asc) }
+ scope :foreign_key_type, -> { columns_hash.key?('constraint_type') ? foreign_key : all }
def self.table_available?
connection.table_exists?(table_name)
diff --git a/lib/gitlab/import/import_failure_service.rb b/lib/gitlab/import/import_failure_service.rb
index bebd64b29a9..2f6ffc4c844 100644
--- a/lib/gitlab/import/import_failure_service.rb
+++ b/lib/gitlab/import/import_failure_service.rb
@@ -52,8 +52,8 @@ module Gitlab
track_exception
persist_failure
- track_metrics if metrics
import_state.mark_as_failed(exception.message) if fail_import
+ track_metrics if metrics
end
private
@@ -89,8 +89,13 @@ module Gitlab
)
end
+ def import_metrics
+ @import_metrics ||= Gitlab::Import::Metrics.new("#{project.import_type}_importer", project)
+ end
+
def track_metrics
- Gitlab::Import::Metrics.new("#{project.import_type}_importer", project).track_failed_import
+ import_metrics.track_failed_import
+ import_metrics.track_import_state
end
end
end
diff --git a/lib/gitlab/import/metrics.rb b/lib/gitlab/import/metrics.rb
index 7a0cf1682a6..82f8cf8dbc6 100644
--- a/lib/gitlab/import/metrics.rb
+++ b/lib/gitlab/import/metrics.rb
@@ -26,6 +26,7 @@ module Gitlab
observe_histogram
projects_counter.increment
track_finish_metric
+ track_import_state
end
def track_failed_import
@@ -34,6 +35,18 @@ module Gitlab
track_usage_event(:github_import_project_failure, project.id)
end
+ def track_import_state
+ return unless project.github_import?
+
+ Gitlab::Tracking.event(
+ importer,
+ 'create',
+ label: 'github_import_project_state',
+ project: project,
+ extra: { import_type: 'github', state: project.beautified_import_status_name }
+ )
+ end
+
def issues_counter
@issues_counter ||= Gitlab::Metrics.counter(
:"#{importer}_imported_issues_total",
diff --git a/lib/sidebars/projects/menus/deployments_menu.rb b/lib/sidebars/projects/menus/deployments_menu.rb
index 4d4e65e9795..fa6c70cfd3d 100644
--- a/lib/sidebars/projects/menus/deployments_menu.rb
+++ b/lib/sidebars/projects/menus/deployments_menu.rb
@@ -34,6 +34,11 @@ module Sidebars
'deployments'
end
+ override :serialize_as_menu_item_args
+ def serialize_as_menu_item_args
+ nil
+ end
+
private
def feature_flags_menu_item
@@ -44,6 +49,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Feature Flags'),
link: project_feature_flags_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :feature_flags },
container_html_options: { class: 'shortcuts-feature-flags' },
item_id: :feature_flags
@@ -58,6 +64,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Environments'),
link: project_environments_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :environments },
container_html_options: { class: 'shortcuts-environments' },
item_id: :environments
@@ -73,6 +80,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Releases'),
link: project_releases_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
item_id: :releases,
active_routes: { controller: :releases },
container_html_options: { class: 'shortcuts-deployments-releases' }
@@ -87,6 +95,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Pages'),
link: project_pages_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { path: 'pages#show' },
item_id: :pages
)
diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb
index 390df0af1d7..701169e5cd3 100644
--- a/lib/sidebars/projects/menus/infrastructure_menu.rb
+++ b/lib/sidebars/projects/menus/infrastructure_menu.rb
@@ -32,6 +32,11 @@ module Sidebars
'cloud-gear'
end
+ override :serialize_as_menu_item_args
+ def serialize_as_menu_item_args
+ nil
+ end
+
private
def feature_enabled?
@@ -46,6 +51,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Kubernetes clusters'),
link: project_clusters_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: [:cluster_agents, :clusters] },
container_html_options: { class: 'shortcuts-kubernetes' },
hint_html_options: kubernetes_hint_html_options,
@@ -74,6 +80,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Terraform'),
link: project_terraform_index_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :terraform },
item_id: :terraform
)
@@ -95,6 +102,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Google Cloud'),
link: project_google_cloud_configuration_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: %w[
projects/google_cloud/configuration
projects/google_cloud/service_accounts
diff --git a/lib/sidebars/projects/menus/packages_registries_menu.rb b/lib/sidebars/projects/menus/packages_registries_menu.rb
index fc7c564574a..d5b590a03aa 100644
--- a/lib/sidebars/projects/menus/packages_registries_menu.rb
+++ b/lib/sidebars/projects/menus/packages_registries_menu.rb
@@ -23,6 +23,11 @@ module Sidebars
'package'
end
+ override :serialize_as_menu_item_args
+ def serialize_as_menu_item_args
+ nil
+ end
+
private
def packages_registry_menu_item
@@ -33,6 +38,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Package Registry'),
link: project_packages_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :packages },
item_id: :packages_registry,
container_html_options: { class: 'shortcuts-container-registry' }
@@ -47,6 +53,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Container Registry'),
link: project_container_registry_index_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: 'projects/registry/repositories' },
item_id: :container_registry
)
@@ -60,6 +67,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Infrastructure Registry'),
link: project_infrastructure_registry_index_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :infrastructure_registry },
item_id: :infrastructure_registry
)
@@ -75,6 +83,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Harbor Registry'),
link: project_harbor_repositories_path(context.project),
+ super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
active_routes: { controller: :harbor_registry },
item_id: :harbor_registry
)
diff --git a/lib/sidebars/projects/menus/snippets_menu.rb b/lib/sidebars/projects/menus/snippets_menu.rb
index 060341b3c51..a1ba85e2b04 100644
--- a/lib/sidebars/projects/menus/snippets_menu.rb
+++ b/lib/sidebars/projects/menus/snippets_menu.rb
@@ -35,6 +35,14 @@ module Sidebars
def active_routes
{ controller: :snippets }
end
+
+ override :serialize_as_menu_item_args
+ def serialize_as_menu_item_args
+ super.deep_merge({
+ super_sidebar_parent: ::Sidebars::Projects::Menus::RepositoryMenu,
+ super_sidebar_before: :contributors
+ })
+ end
end
end
end
diff --git a/lib/sidebars/projects/super_sidebar_menus/operations_menu.rb b/lib/sidebars/projects/super_sidebar_menus/operations_menu.rb
new file mode 100644
index 00000000000..5490aac5a65
--- /dev/null
+++ b/lib/sidebars/projects/super_sidebar_menus/operations_menu.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module SuperSidebarMenus
+ class OperationsMenu < ::Sidebars::Menu
+ override :title
+ def title
+ _('Operations')
+ end
+
+ override :sprite_icon
+ def sprite_icon
+ 'deployments'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/projects/super_sidebar_panel.rb b/lib/sidebars/projects/super_sidebar_panel.rb
index f0ebea92525..2f2f3714cef 100644
--- a/lib/sidebars/projects/super_sidebar_panel.rb
+++ b/lib/sidebars/projects/super_sidebar_panel.rb
@@ -14,12 +14,11 @@ module Sidebars
add_menu(Sidebars::StaticMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::PlanMenu.new(context))
+ # "Develop" menu
pick_from_old_menus(old_menus, Sidebars::Projects::Menus::RepositoryMenu)
pick_from_old_menus(old_menus, Sidebars::Projects::Menus::CiCdMenu)
pick_from_old_menus(old_menus, Sidebars::Projects::Menus::SecurityComplianceMenu)
- pick_from_old_menus(old_menus, Sidebars::Projects::Menus::DeploymentsMenu)
- pick_from_old_menus(old_menus, Sidebars::Projects::Menus::PackagesRegistriesMenu)
- pick_from_old_menus(old_menus, Sidebars::Projects::Menus::InfrastructureMenu)
+ add_menu(Sidebars::Projects::SuperSidebarMenus::OperationsMenu.new(context))
pick_from_old_menus(old_menus, Sidebars::Projects::Menus::MonitorMenu)
pick_from_old_menus(old_menus, Sidebars::Projects::Menus::AnalyticsMenu)
add_menu(Sidebars::UncategorizedMenu.new(context))
diff --git a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
index 2ae68fc64cf..124b6c9cd44 100644
--- a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
@@ -18,10 +18,7 @@ module QA
end
end
- context 'when added to parent group', quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/392816',
- type: :investigating
- } do
+ context 'when added to parent group' do
let!(:parent_group_user) do
Resource::User.fabricate_via_api! do |user|
user.api_client = admin_api_client
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 513e67ea247..3048a40809e 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -71,12 +71,6 @@ describe('diffs/components/app', () => {
},
provide,
store,
- stubs: {
- DynamicScroller: {
- template: `<div><slot :item="$store.state.diffs.diffFiles[0]"></slot></div>`,
- },
- DynamicScrollerItem: true,
- },
});
}
@@ -294,13 +288,13 @@ describe('diffs/components/app', () => {
it('does not render empty state when diff files exist', () => {
createComponent({}, ({ state }) => {
- state.diffs.diffFiles.push({
- id: 1,
- });
+ state.diffs.diffFiles.push({ id: 1 });
});
expect(wrapper.findComponent(NoChanges).exists()).toBe(false);
- expect(wrapper.findAllComponents(DiffFile).length).toBe(1);
+ expect(wrapper.findComponent({ name: 'DynamicScroller' }).props('items')).toBe(
+ store.state.diffs.diffFiles,
+ );
});
});
@@ -581,7 +575,10 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ sha: '123' });
});
- expect(wrapper.findComponent(DiffFile).exists()).toBe(true);
+ expect(wrapper.findComponent({ name: 'DynamicScroller' }).exists()).toBe(true);
+ expect(wrapper.findComponent({ name: 'DynamicScroller' }).props('items')).toBe(
+ store.state.diffs.diffFiles,
+ );
});
it("doesn't render tree list when no changes exist", () => {
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 78765204322..614742d026f 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -236,13 +236,17 @@ describe('DiffsStoreActions', () => {
it('should show no warning on any other status code', async () => {
mock.onGet(endpointMetadata).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
- await testAction(
- diffActions.fetchDiffFilesMeta,
- {},
- { endpointMetadata, diffViewType: 'inline', showWhitespace: true },
- [{ type: types.SET_LOADING, payload: true }],
- [],
- );
+ try {
+ await testAction(
+ diffActions.fetchDiffFilesMeta,
+ {},
+ { endpointMetadata, diffViewType: 'inline', showWhitespace: true },
+ [{ type: types.SET_LOADING, payload: true }],
+ [],
+ );
+ } catch (error) {
+ expect(error.response.status).toBe(HTTP_STATUS_INTERNAL_SERVER_ERROR);
+ }
expect(createAlert).not.toHaveBeenCalled();
});
diff --git a/spec/graphql/types/root_storage_statistics_type_spec.rb b/spec/graphql/types/root_storage_statistics_type_spec.rb
index 07c8378e7a6..5dde6aa8b14 100644
--- a/spec/graphql/types/root_storage_statistics_type_spec.rb
+++ b/spec/graphql/types/root_storage_statistics_type_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :wiki_size, :snippets_size,
:pipeline_artifacts_size, :uploads_size, :dependency_proxy_size,
- :container_registry_size)
+ :container_registry_size, :registry_size_estimated)
end
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
diff --git a/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb b/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
index d9fa6b931ad..4ccbf44af52 100644
--- a/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
+RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout, feature_category: :product_analytics do
let(:ce_temp_dir) { Dir.mktmpdir }
let(:ee_temp_dir) { Dir.mktmpdir }
let(:timestamp) { Time.current.to_i }
@@ -30,7 +30,8 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
let(:file_name) { Dir.children(ce_temp_dir).first }
it 'creates CE event definition file using the template' do
- sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event.yml'))).load_raw!
+ sample_event = ::Gitlab::Config::Loader::Yaml
+ .new(fixture_file(File.join(sample_event_dir, 'sample_event.yml'))).load_raw!
described_class.new([], generator_options).invoke_all
@@ -62,25 +63,13 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
end
end
- context 'event definition already exists' do
+ context 'when event definition with same file name already exists' do
before do
stub_const('Gitlab::VERSION', '12.11.0-pre')
described_class.new([], generator_options).invoke_all
end
- it 'overwrites event definition --force flag set to true' do
- sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event.yml'))).load_raw!
-
- stub_const('Gitlab::VERSION', '13.11.0-pre')
- described_class.new([], generator_options.merge('force' => true)).invoke_all
-
- event_definition_path = File.join(ce_temp_dir, file_name)
- event_data = ::Gitlab::Config::Loader::Yaml.new(File.read(event_definition_path)).load_raw!
-
- expect(event_data).to eq(sample_event)
- end
-
- it 'raises error when --force flag set to false' do
+ it 'raises error' do
expect { described_class.new([], generator_options.merge('force' => false)).invoke_all }
.to raise_error(StandardError, /Event definition already exists at/)
end
@@ -90,7 +79,8 @@ RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
let(:file_name) { Dir.children(ee_temp_dir).first }
it 'creates EE event definition file using the template' do
- sample_event = ::Gitlab::Config::Loader::Yaml.new(fixture_file(File.join(sample_event_dir, 'sample_event_ee.yml'))).load_raw!
+ sample_event = ::Gitlab::Config::Loader::Yaml
+ .new(fixture_file(File.join(sample_event_dir, 'sample_event_ee.yml'))).load_raw!
described_class.new([], generator_options.merge('ee' => true)).invoke_all
diff --git a/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb b/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb
new file mode 100644
index 00000000000..84259505683
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::MigrateRemediationsForVulnerabilityFindings,
+ feature_category: :vulnerability_management do
+ let(:vulnerability_occurrences) { table(:vulnerability_occurrences) }
+ let(:vulnerability_findings_remediations) { table(:vulnerability_findings_remediations) }
+ let(:vulnerability_remediations) { table(:vulnerability_remediations) }
+ let(:remediation_hash) { { summary: 'summary', diff: "ZGlmZiAtLWdp" } }
+ let(:namespace1) { table(:namespaces).create!(name: 'namespace 1', path: 'namespace1') }
+ let(:project1) { table(:projects).create!(namespace_id: namespace1.id, project_namespace_id: namespace1.id) }
+ let(:user) { table(:users).create!(email: 'test1@example.com', projects_limit: 5) }
+
+ let(:scanner1) do
+ table(:vulnerability_scanners).create!(project_id: project1.id, external_id: 'test 1', name: 'test scanner 1')
+ end
+
+ let(:stating_id) { vulnerability_occurrences.pluck(:id).min }
+ let(:end_id) { vulnerability_occurrences.pluck(:id).max }
+
+ let(:migration) do
+ described_class.new(
+ start_id: stating_id,
+ end_id: end_id,
+ batch_table: :vulnerability_occurrences,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 2,
+ connection: ApplicationRecord.connection
+ )
+ end
+
+ subject(:perform_migration) { migration.perform }
+
+ context 'without the presence of remediation key' do
+ before do
+ create_finding!(project1.id, scanner1.id, { other_keys: 'test' })
+ end
+
+ it 'does not create any remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.not_to change { vulnerability_remediations.count }
+ end
+ end
+
+ context 'with remediation equals to an array of nil element' do
+ before do
+ create_finding!(project1.id, scanner1.id, { remediations: [nil] })
+ end
+
+ it 'does not create any remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.not_to change { vulnerability_remediations.count }
+ end
+ end
+
+ context 'with remediation equals to an array of duplicated elements' do
+ let!(:finding) do
+ create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash, remediation_hash] })
+ end
+
+ it 'creates new remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.to change { vulnerability_remediations.count }.by(1)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding.id).length).to eq(1)
+ end
+ end
+
+ context 'with existing remediations within raw_metadata' do
+ let!(:finding1) { create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash] }) }
+ let!(:finding2) { create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash] }) }
+
+ it 'creates new remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.to change { vulnerability_remediations.count }.by(1)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding1.id).length).to eq(1)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding2.id).length).to eq(1)
+ end
+
+ context 'when create throws exception other than ActiveRecord::RecordNotUnique' do
+ before do
+ allow(migration).to receive(:create_finding_remediations).and_raise(StandardError)
+ end
+
+ it 'rolls back all related transactions' do
+ expect(Gitlab::AppLogger).to receive(:error).with({
+ class: described_class.name, message: StandardError.to_s, model_id: finding1.id
+ })
+ expect(Gitlab::AppLogger).to receive(:error).with({
+ class: described_class.name, message: StandardError.to_s, model_id: finding2.id
+ })
+ expect { perform_migration }.not_to change { vulnerability_remediations.count }
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding1.id).length).to eq(0)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding2.id).length).to eq(0)
+ end
+ end
+ end
+
+ context 'with existing remediation records' do
+ let!(:finding) { create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash] }) }
+
+ before do
+ vulnerability_remediations.create!(project_id: project1.id, summary: remediation_hash[:summary],
+ checksum: checksum(remediation_hash[:diff]), file: Tempfile.new.path)
+ end
+
+ it 'does not create new remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.not_to change { vulnerability_remediations.count }
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding.id).length).to eq(1)
+ end
+ end
+
+ context 'with same raw_metadata for different projects' do
+ let(:namespace2) { table(:namespaces).create!(name: 'namespace 2', path: 'namespace2') }
+ let(:project2) { table(:projects).create!(namespace_id: namespace2.id, project_namespace_id: namespace2.id) }
+ let(:scanner2) do
+ table(:vulnerability_scanners).create!(project_id: project2.id, external_id: 'test 2', name: 'test scanner 2')
+ end
+
+ let!(:finding1) { create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash] }) }
+ let!(:finding2) { create_finding!(project2.id, scanner2.id, { remediations: [remediation_hash] }) }
+
+ it 'creates new remediation for each project' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.to change { vulnerability_remediations.count }.by(2)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding1.id).length).to eq(1)
+ expect(vulnerability_findings_remediations.where(vulnerability_occurrence_id: finding2.id).length).to eq(1)
+ end
+ end
+
+ private
+
+ def create_finding!(project_id, scanner_id, raw_metadata)
+ vulnerability = table(:vulnerabilities).create!(project_id: project_id, author_id: user.id, title: 'test',
+ severity: 4, confidence: 4, report_type: 0)
+
+ identifier = table(:vulnerability_identifiers).create!(project_id: project_id, external_type: 'uuid-v5',
+ external_id: 'uuid-v5', fingerprint: OpenSSL::Digest::SHA256.hexdigest(vulnerability.id.to_s),
+ name: 'Identifier for UUIDv5 2 2')
+
+ table(:vulnerability_occurrences).create!(
+ vulnerability_id: vulnerability.id, project_id: project_id, scanner_id: scanner_id,
+ primary_identifier_id: identifier.id, name: 'test', severity: 4, confidence: 4, report_type: 0,
+ uuid: SecureRandom.uuid, project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" },
+ location_fingerprint: 'test', metadata_version: 'test',
+ raw_metadata: raw_metadata.to_json)
+ end
+
+ def checksum(value)
+ sha = Digest::SHA256.hexdigest(value)
+ Gitlab::Database::ShaAttribute.new.serialize(sha)
+ end
+end
diff --git a/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb b/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb
index ab06c7c7e82..08d255a4bb8 100644
--- a/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb
@@ -33,6 +33,7 @@ RSpec.describe Gitlab::Database::AsyncConstraints::MigrationHelpers, feature_cat
record = constraint_model.find_by(table_name: table_name)
expect(record.name).to start_with('fk_')
+ expect(record).to be_foreign_key
end
context 'when an explicit name is given' do
@@ -46,6 +47,7 @@ RSpec.describe Gitlab::Database::AsyncConstraints::MigrationHelpers, feature_cat
record = constraint_model.find_by(name: fk_name)
expect(record.table_name).to eq(table_name)
+ expect(record).to be_foreign_key
end
end
@@ -81,33 +83,50 @@ RSpec.describe Gitlab::Database::AsyncConstraints::MigrationHelpers, feature_cat
end
describe '#unprepare_async_foreign_key_validation' do
- before do
- migration.prepare_async_foreign_key_validation(table_name, column_name, name: fk_name)
- end
-
- it 'destroys the record' do
- expect do
- migration.unprepare_async_foreign_key_validation(table_name, column_name)
- end.to change { constraint_model.where(table_name: table_name).count }.by(-1)
- end
-
- context 'when an explicit name is given' do
- let(:fk_name) { 'my_test_async_fk' }
+ context 'with foreign keys' do
+ before do
+ migration.prepare_async_foreign_key_validation(table_name, column_name, name: fk_name)
+ end
it 'destroys the record' do
expect do
- migration.unprepare_async_foreign_key_validation(table_name, name: fk_name)
- end.to change { constraint_model.where(name: fk_name).count }.by(-1)
+ migration.unprepare_async_foreign_key_validation(table_name, column_name)
+ end.to change { constraint_model.where(table_name: table_name).count }.by(-1)
+ end
+
+ context 'when an explicit name is given' do
+ let(:fk_name) { 'my_test_async_fk' }
+
+ it 'destroys the record' do
+ expect do
+ migration.unprepare_async_foreign_key_validation(table_name, name: fk_name)
+ end.to change { constraint_model.where(name: fk_name).count }.by(-1)
+ end
+ end
+
+ context 'when the async fk validation table does not exist' do
+ it 'does not raise an error' do
+ connection.drop_table(constraint_model.table_name)
+
+ expect(constraint_model).not_to receive(:find_by)
+
+ expect { migration.unprepare_async_foreign_key_validation(table_name, column_name) }.not_to raise_error
+ end
end
end
- context 'when the async fk validation table does not exist' do
- it 'does not raise an error' do
- connection.drop_table(constraint_model.table_name)
+ context 'with other types of constraints' do
+ let(:name) { 'my_test_async_constraint' }
+ let(:constraint) { create(:postgres_async_constraint_validation, table_name: table_name, name: name) }
- expect(constraint_model).not_to receive(:find_by)
+ it 'does not destroy the record' do
+ constraint.update_column(:constraint_type, 99)
+
+ expect do
+ migration.unprepare_async_foreign_key_validation(table_name, name: name)
+ end.not_to change { constraint_model.where(name: name).count }
- expect { migration.unprepare_async_foreign_key_validation(table_name, column_name) }.not_to raise_error
+ expect(constraint).to be_present
end
end
end
diff --git a/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb b/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb
index a8e136dd22c..7fea2eb1bcc 100644
--- a/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb
+++ b/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb
@@ -30,6 +30,24 @@ RSpec.describe Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValida
it { is_expected.to eq([new_validation, failed_validation]) }
end
+
+ describe '.foreign_key_type' do
+ before do
+ new_validation.update_column(:constraint_type, 99)
+ end
+
+ subject { described_class.foreign_key_type }
+
+ it { is_expected.to eq([failed_validation]) }
+
+ it 'does not apply the filter if the column is not present' do
+ expect(described_class).to receive(:columns_hash).and_wrap_original do |method|
+ method.call.except('constraint_type')
+ end
+
+ is_expected.to match_array([failed_validation, new_validation])
+ end
+ end
end
describe '.table_available?' do
diff --git a/spec/lib/gitlab/import/import_failure_service_spec.rb b/spec/lib/gitlab/import/import_failure_service_spec.rb
index eb71b307b8d..fc02c6bd4ca 100644
--- a/spec/lib/gitlab/import/import_failure_service_spec.rb
+++ b/spec/lib/gitlab/import/import_failure_service_spec.rb
@@ -141,6 +141,7 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
.with("#{project.import_type}_importer", project)
.and_return(metrics_double)
expect(metrics_double).to receive(:track_failed_import)
+ expect(metrics_double).to receive(:track_import_state)
service.execute
end
diff --git a/spec/lib/gitlab/import/metrics_spec.rb b/spec/lib/gitlab/import/metrics_spec.rb
index 9b8b58d00f3..f0140a975b1 100644
--- a/spec/lib/gitlab/import/metrics_spec.rb
+++ b/spec/lib/gitlab/import/metrics_spec.rb
@@ -60,6 +60,41 @@ RSpec.describe Gitlab::Import::Metrics, :aggregate_failures do
end
end
+ describe '#track_import_state' do
+ context 'when project is not a github import' do
+ it 'does not emit importer metrics' do
+ subject.track_import_state
+
+ expect_no_snowplow_event(
+ category: :test_importer,
+ action: 'create',
+ label: 'github_import_project_state',
+ project: project,
+ extra: { import_type: 'github', state: 'failed' }
+ )
+ end
+ end
+
+ context 'when project is a github import' do
+ before do
+ project.import_type = 'github'
+ allow(project).to receive(:import_status).and_return('failed')
+ end
+
+ it 'emits importer metrics' do
+ subject.track_import_state
+
+ expect_snowplow_event(
+ category: :test_importer,
+ action: 'create',
+ label: 'github_import_project_state',
+ project: project,
+ extra: { import_type: 'github', state: 'failed' }
+ )
+ end
+ end
+ end
+
describe '#track_finished_import' do
before do
allow(Gitlab::Metrics).to receive(:histogram) { histogram }
@@ -92,6 +127,33 @@ RSpec.describe Gitlab::Import::Metrics, :aggregate_failures do
subject.track_finished_import
expect(histogram).to have_received(:observe).with({ importer: :test_importer }, anything)
+ expect_no_snowplow_event(
+ category: :test_importer,
+ action: 'create',
+ label: 'github_import_project_state',
+ project: project,
+ extra: { import_type: 'github', state: 'completed' }
+ )
+ end
+ end
+
+ context 'when project is a github import' do
+ before do
+ project.import_type = 'github'
+ allow(project).to receive(:import_status).and_return('finished')
+ allow(project).to receive(:import_finished?).and_return(true)
+ end
+
+ it 'emits snowplow metrics' do
+ subject.track_finished_import
+
+ expect_snowplow_event(
+ category: :test_importer,
+ action: 'create',
+ label: 'github_import_project_state',
+ project: project,
+ extra: { import_type: 'github', state: 'completed' }
+ )
end
end
end
diff --git a/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb b/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb
new file mode 100644
index 00000000000..df3f7e6cdab
--- /dev/null
+++ b/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::SuperSidebarMenus::OperationsMenu, feature_category: :navigation do
+ subject { described_class.new({}) }
+
+ it 'has title and sprite_icon' do
+ expect(subject.title).to eq(_("Operations"))
+ expect(subject.sprite_icon).to eq("deployments")
+ end
+end
diff --git a/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb
index a4df46ca493..d6fc3fd8fe1 100644
--- a/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb
+++ b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb
@@ -30,9 +30,7 @@ RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigat
Sidebars::Projects::Menus::RepositoryMenu,
Sidebars::Projects::Menus::CiCdMenu,
Sidebars::Projects::Menus::SecurityComplianceMenu,
- Sidebars::Projects::Menus::DeploymentsMenu,
- Sidebars::Projects::Menus::PackagesRegistriesMenu,
- Sidebars::Projects::Menus::InfrastructureMenu,
+ Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
Sidebars::Projects::Menus::MonitorMenu,
Sidebars::Projects::Menus::AnalyticsMenu,
Sidebars::UncategorizedMenu,
@@ -41,7 +39,7 @@ RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigat
end
it "is exposed as a renderable menu" do
- expect(subject.renderable_menus.map(&:class)).to eq(category_menu)
+ expect(subject.instance_variable_get(:@menus).map(&:class)).to eq(category_menu)
end
end
end
diff --git a/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb b/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb
new file mode 100644
index 00000000000..d22aeeaa254
--- /dev/null
+++ b/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleMigrationForRemediation, :migration, feature_category: :vulnerability_management do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules a batched background migration' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :vulnerability_occurrences,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20230125195503_queue_backfill_compliance_violations_spec.rb b/spec/migrations/20230125195503_queue_backfill_compliance_violations_spec.rb
new file mode 100644
index 00000000000..a70f9820855
--- /dev/null
+++ b/spec/migrations/20230125195503_queue_backfill_compliance_violations_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueBackfillComplianceViolations, feature_category: :compliance_management do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of merge_request_compliance_violations' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ table_name: :merge_requests_compliance_violations,
+ column_name: :id,
+ interval: described_class::INTERVAL,
+ batch_size: described_class::BATCH_SIZE
+ )
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
index 7d04817b621..3fba2ac003b 100644
--- a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
+++ b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
@@ -66,22 +66,6 @@ RSpec.describe Preloaders::UserMaxAccessLevelInGroupsPreloader do
create(:group_group_link, :guest, shared_with_group: group1, shared_group: group4)
end
- context 'when `include_memberships_from_group_shares_in_preloader` feature flag is disabled' do
- before do
- stub_feature_flags(include_memberships_from_group_shares_in_preloader: false)
- end
-
- it 'sets access_level to `NO_ACCESS` in cache for groups arising from group shares' do
- described_class.new(groups, user).execute
-
- groups.each do |group|
- cached_access_level = group.max_member_access_for_user(user)
-
- expect(cached_access_level).to eq(Gitlab::Access::NO_ACCESS)
- end
- end
- end
-
it 'sets the right access level in cache for groups arising from group shares' do
described_class.new(groups, user).execute
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e0d46bab1f4..7d431de9f07 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -3594,6 +3594,44 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
end
end
+ describe '#beautified_import_status_name' do
+ context 'when import not finished' do
+ it 'returns the right beautified import status' do
+ project = create(:project, :import_started)
+
+ expect(project.beautified_import_status_name).to eq('started')
+ end
+ end
+
+ context 'when import is finished' do
+ context 'when import is partially completed' do
+ it 'returns partially completed' do
+ project = create(:project)
+
+ create(:import_state, project: project, status: 'finished', checksums: {
+ 'fetched' => { 'labels' => 10 },
+ 'imported' => { 'labels' => 9 }
+ })
+
+ expect(project.beautified_import_status_name).to eq('partially completed')
+ end
+ end
+
+ context 'when import is fully completed' do
+ it 'returns completed' do
+ project = create(:project)
+
+ create(:import_state, project: project, status: 'finished', checksums: {
+ 'fetched' => { 'labels' => 10 },
+ 'imported' => { 'labels' => 10 }
+ })
+
+ expect(project.beautified_import_status_name).to eq('completed')
+ end
+ end
+ end
+ end
+
describe '#add_import_job' do
let(:import_jid) { '123' }
diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb
index 2b9ff442f76..29ea20210c7 100644
--- a/spec/requests/projects/issues_controller_spec.rb
+++ b/spec/requests/projects/issues_controller_spec.rb
@@ -39,6 +39,11 @@ RSpec.describe Projects::IssuesController, feature_category: :team_planning do
describe 'incident tabs' do
let_it_be(:incident) { create(:incident, project: project) }
+ it 'redirects to the issues route for non-incidents' do
+ get incident_issue_project_issue_path(project, issue, 'timeline')
+ expect(response).to redirect_to project_issue_path(project, issue)
+ end
+
it 'responds with selected tab for incidents' do
get incident_issue_project_issue_path(project, incident, 'timeline')
expect(response.body).to match(/&quot;currentTab&quot;:&quot;timeline&quot;/)
diff --git a/spec/services/import/github/cancel_project_import_service_spec.rb b/spec/services/import/github/cancel_project_import_service_spec.rb
index 77b8771ee65..114265315b0 100644
--- a/spec/services/import/github/cancel_project_import_service_spec.rb
+++ b/spec/services/import/github/cancel_project_import_service_spec.rb
@@ -14,6 +14,18 @@ RSpec.describe Import::Github::CancelProjectImportService do
it 'update import state to be canceled' do
expect(import_cancel.execute).to eq({ status: :success, project: project })
end
+
+ it 'tracks canceled imports' do
+ metrics_double = instance_double('Gitlab::Import::Metrics')
+
+ expect(Gitlab::Import::Metrics)
+ .to receive(:new)
+ .with(:github_importer, project)
+ .and_return(metrics_double)
+ expect(metrics_double).to receive(:track_import_state)
+
+ import_cancel.execute
+ end
end
context 'when import is finished' do
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 6e3f47b9afc..a14b3fd51be 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-rc43
+ gitlab.com/gitlab-org/gitaly/v15 v15.9.0
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 2240d85273e..dfd6f45f5a6 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-rc43 h1:yHDCgmgeCC+R1F40HleRpPSPe3MVCmS8okvolxZ1Ack=
-gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc43/go.mod h1:MLAmjPsXan0TixWBOnF2GUTjHcNLoAiYv1x1LRx7gHQ=
+gitlab.com/gitlab-org/gitaly/v15 v15.9.0 h1:4kBEi+hyjTamWwbvnPMZTYuP4wnL8bwPXDFyDqTGuBc=
+gitlab.com/gitlab-org/gitaly/v15 v15.9.0/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=