From 386dcdbe9d3cef9d5fa79c4582a722db27fe2c57 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 22 Jan 2024 21:08:53 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/rails/shared.gitlab-ci.yml | 8 + .ruby-version | 2 +- Gemfile | 2 +- Gemfile.checksum | 6 +- Gemfile.lock | 9 +- app/assets/javascripts/diffs/components/app.vue | 17 +- .../lib/utils/datetime/date_calculation_utility.js | 13 +- .../javascripts/notes/components/comment_form.vue | 7 +- .../javascripts/notes/components/note_form.vue | 2 + .../javascripts/notes/components/notes_app.vue | 18 +- .../storage/components/namespace_storage_app.vue | 64 ++++++- .../storage/components/project_list.vue | 208 +++++++++++++++++++++ .../storage/components/storage_type_help_link.vue | 36 ++++ app/services/service_ping/submit_service.rb | 2 +- ..._request_click_add_to_review_on_changes_tab.yml | 20 ++ ...request_click_add_to_review_on_overview_tab.yml | 20 ++ ...e_request_click_start_review_on_changes_tab.yml | 20 ++ ..._request_click_start_review_on_overview_tab.yml | 20 ++ .../github_importer_attachments.yml | 9 - ..._click_add_to_review_on_changes_tab_monthly.yml | 26 +++ ...click_add_to_review_on_overview_tab_monthly.yml | 26 +++ ...t_click_start_review_on_changes_tab_monthly.yml | 26 +++ ..._click_start_review_on_overview_tab_monthly.yml | 26 +++ ...t_click_add_to_review_on_changes_tab_weekly.yml | 26 +++ ..._click_add_to_review_on_overview_tab_weekly.yml | 26 +++ ...st_click_start_review_on_changes_tab_weekly.yml | 26 +++ ...t_click_start_review_on_overview_tab_weekly.yml | 26 +++ ..._request_click_add_to_review_on_changes_tab.yml | 26 +++ ...request_click_add_to_review_on_overview_tab.yml | 26 +++ ...e_request_click_start_review_on_changes_tab.yml | 26 +++ ..._request_click_start_review_on_overview_tab.yml | 26 +++ doc/api/resource_state_events.md | 3 + .../documentation/restful_api_styleguide.md | 17 +- doc/development/documentation/styleguide/index.md | 13 +- doc/user/ai_features.md | 32 ++-- lib/bulk_imports/common/pipelines/wiki_pipeline.rb | 7 +- .../projects/pipelines/repository_pipeline.rb | 7 +- .../pipelines/snippets_repository_pipeline.rb | 3 +- lib/gitlab/database.rb | 2 +- .../error_repository/open_api_strategy.rb | 6 +- .../github_gists_import/importer/gist_importer.rb | 12 +- .../importer/attachments/base_importer.rb | 2 - lib/gitlab/kubernetes/kube_client.rb | 6 +- lib/gitlab/octokit/middleware.rb | 5 +- lib/service_ping/service_ping_settings.rb | 2 +- spec/frontend/diffs/components/app_spec.js | 36 ++++ spec/frontend/lib/utils/datetime_utility_spec.js | 9 + .../frontend/notes/components/comment_form_spec.js | 19 +- spec/frontend/notes/components/note_form_spec.js | 51 +++-- spec/frontend/notes/components/notes_app_spec.js | 37 ++++ .../components/storage_type_help_link_spec.js | 49 +++++ spec/frontend/usage_quotas/storage/mock_data.js | 3 + .../importer/gist_importer_spec.rb | 14 +- .../importer/attachments/issues_importer_spec.rb | 14 -- .../attachments/merge_requests_importer_spec.rb | 14 -- .../importer/attachments/notes_importer_spec.rb | 14 -- .../importer/attachments/releases_importer_spec.rb | 14 -- .../lib/service_ping/service_ping_settings_spec.rb | 8 +- .../submit_service_ping_service_spec.rb | 8 +- 59 files changed, 1053 insertions(+), 149 deletions(-) create mode 100644 app/assets/javascripts/usage_quotas/storage/components/project_list.vue create mode 100644 app/assets/javascripts/usage_quotas/storage/components/storage_type_help_link.vue create mode 100644 config/events/merge_request_click_add_to_review_on_changes_tab.yml create mode 100644 config/events/merge_request_click_add_to_review_on_overview_tab.yml create mode 100644 config/events/merge_request_click_start_review_on_changes_tab.yml create mode 100644 config/events/merge_request_click_start_review_on_overview_tab.yml delete mode 100644 config/feature_flags/gitlab_com_derisk/github_importer_attachments.yml create mode 100644 config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_changes_tab_monthly.yml create mode 100644 config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_overview_tab_monthly.yml create mode 100644 config/metrics/counts_28d/count_total_merge_request_click_start_review_on_changes_tab_monthly.yml create mode 100644 config/metrics/counts_28d/count_total_merge_request_click_start_review_on_overview_tab_monthly.yml create mode 100644 config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_changes_tab_weekly.yml create mode 100644 config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_overview_tab_weekly.yml create mode 100644 config/metrics/counts_7d/count_total_merge_request_click_start_review_on_changes_tab_weekly.yml create mode 100644 config/metrics/counts_7d/count_total_merge_request_click_start_review_on_overview_tab_weekly.yml create mode 100644 config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_changes_tab.yml create mode 100644 config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_overview_tab.yml create mode 100644 config/metrics/counts_all/count_total_merge_request_click_start_review_on_changes_tab.yml create mode 100644 config/metrics/counts_all/count_total_merge_request_click_start_review_on_overview_tab.yml create mode 100644 spec/frontend/usage_quotas/storage/components/storage_type_help_link_spec.js diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml index 1f420b9b8ec..04811baf932 100644 --- a/.gitlab/ci/rails/shared.gitlab-ci.yml +++ b/.gitlab/ci/rails/shared.gitlab-ci.yml @@ -115,6 +115,14 @@ include: --input-files "rspec/rspec-*.json" \ --merge_request_iid "$CI_MERGE_REQUEST_IID"; fi + if [ "$ALLOW_KNAPSACK_REPORT_CREATE_ISSUES" == "true" ]; then + bundle exec knapsack-report-issues \ + --token "${KNAPSACK_REPORT_ISSUES_PROJECT_TOKEN}" \ + --project "gitlab-org/gitlab" \ + --input-file knapsack/rspec_*_report.json \ + --expected-report node_specs_expected_duration.json \ + --merge_request_iid "$CI_MERGE_REQUEST_IID"; + fi - echo -e "\e[0Ksection_end:`date +%s`:report_results_section\r\e[0K" - tooling/bin/push_job_metrics || true diff --git a/.ruby-version b/.ruby-version index be94e6f53db..b347b11eac8 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.2.3 diff --git a/Gemfile b/Gemfile index 01b0b9b7c86..312c8313ccf 100644 --- a/Gemfile +++ b/Gemfile @@ -518,7 +518,7 @@ group :test do # Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527 gem 'derailed_benchmarks', require: false # rubocop:todo Gemfile/MissingFeatureCategory - gem 'gitlab_quality-test_tooling', '~> 1.12.0', require: false, feature_category: :tooling + gem 'gitlab_quality-test_tooling', '~> 1.13.0', require: false, feature_category: :tooling end gem 'octokit', '~> 6.0' # rubocop:todo Gemfile/MissingFeatureCategory diff --git a/Gemfile.checksum b/Gemfile.checksum index 7ad4c2dc349..dcd0f1e82fe 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -226,7 +226,7 @@ {"name":"gitlab-styles","version":"11.0.0","platform":"ruby","checksum":"0dd8ec066ce9955ac51d3616c6bfded30f75bb526f39ff392ece6f43d5b9406b"}, {"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"}, {"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"}, -{"name":"gitlab_quality-test_tooling","version":"1.12.0","platform":"ruby","checksum":"6d687db96777bd8c87264253a7cc9ce1d71851d2b20a64d594770c35555630b1"}, +{"name":"gitlab_quality-test_tooling","version":"1.13.0","platform":"ruby","checksum":"04c51c0b372a38e030572ab85b997234e139d0d639d617ce1924269021b51328"}, {"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"}, {"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"}, {"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"}, @@ -572,7 +572,7 @@ {"name":"ruby-saml","version":"1.15.0","platform":"ruby","checksum":"3a9dda2b448310f4f90d5cf0967d4b668530fa7994d2a4d9cbfdfa62e35f76a3"}, {"name":"ruby-statistics","version":"3.0.0","platform":"ruby","checksum":"610301370346931cb701e3a8d3d3e28eb65681162cae6066c0c11abf20efdc81"}, {"name":"ruby2_keywords","version":"0.0.5","platform":"ruby","checksum":"ffd13740c573b7301cf7a2e61fc857b2a8e3d3aff32545d6f8300d8bae10e3ef"}, -{"name":"ruby_parser","version":"3.20.3","platform":"ruby","checksum":"8d2289a695dc81ffddcdd5a56e80c9a109806bc0d0b1239a1c852b0c71251c49"}, +{"name":"ruby_parser","version":"3.21.0","platform":"ruby","checksum":"3842893d2f4602dcd93c0a79d77f9ce8e1ce197d41ac533d8e25c684f8f1c56b"}, {"name":"rubyntlm","version":"0.6.3","platform":"ruby","checksum":"5b321456dba3130351f7451f8669f1afa83a0d26fd63cdec285b7b88e667102d"}, {"name":"rubypants","version":"0.2.0","platform":"ruby","checksum":"f07e38eac793655a0323fe91946081052341b9e69807026fcf102346589eedee"}, {"name":"rubyzip","version":"2.3.2","platform":"ruby","checksum":"3f57e3935dc2255c414484fbf8d673b4909d8a6a57007ed754dde39342d2373f"}, @@ -593,7 +593,7 @@ {"name":"sentry-ruby","version":"5.10.0","platform":"ruby","checksum":"115c24c0aee1309210f3a2988fb118e2bec1f11609feeda90e694388b1183619"}, {"name":"sentry-sidekiq","version":"5.10.0","platform":"ruby","checksum":"cc81018d0733fb1be3fb5641c9e0b61030bbeaa1d0b23ca64797d70def7aea1a"}, {"name":"set","version":"1.0.2","platform":"ruby","checksum":"02ffa4de1f2621495e05b72326040dd014d7abbcb02fea698bc600a389992c02"}, -{"name":"sexp_processor","version":"4.17.0","platform":"ruby","checksum":"4daa4874ce1838cd801c65e66ed5d4f140024404a3de7482c36d4ef2604dff6f"}, +{"name":"sexp_processor","version":"4.17.1","platform":"ruby","checksum":"91110946720307f30bf1d549e90d9a529fef40d1fc471c069c8cca7667015da0"}, {"name":"shellany","version":"0.0.1","platform":"ruby","checksum":"0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7"}, {"name":"shoulda-matchers","version":"5.1.0","platform":"ruby","checksum":"a01d20589989e9653ab4a28c67d9db2b82bcf0a2496cf01d5e1a95a4aaaf5b07"}, {"name":"sidekiq","version":"7.1.6","platform":"ruby","checksum":"7859da66d5bcef3c22bea2c3091d08c866890168e003f5bf4dea197dc37843a2"}, diff --git a/Gemfile.lock b/Gemfile.lock index b24601eed37..2f7c295dde6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -732,7 +732,7 @@ GEM omniauth (>= 1.3, < 3) pyu-ruby-sasl (>= 0.0.3.3, < 0.1) rubyntlm (~> 0.5) - gitlab_quality-test_tooling (1.12.0) + gitlab_quality-test_tooling (1.13.0) activesupport (>= 6.1, < 7.2) amatch (~> 0.4.1) gitlab (~> 4.19) @@ -1500,7 +1500,8 @@ GEM rexml ruby-statistics (3.0.0) ruby2_keywords (0.0.5) - ruby_parser (3.20.3) + ruby_parser (3.21.0) + racc (~> 1.5) sexp_processor (~> 4.16) rubyntlm (0.6.3) rubypants (0.2.0) @@ -1547,7 +1548,7 @@ GEM sentry-ruby (~> 5.10.0) sidekiq (>= 3.0) set (1.0.2) - sexp_processor (4.17.0) + sexp_processor (4.17.1) shellany (0.0.1) shoulda-matchers (5.1.0) activesupport (>= 5.2.0) @@ -1914,7 +1915,7 @@ DEPENDENCIES gitlab-utils! gitlab_chronic_duration (~> 0.12) gitlab_omniauth-ldap (~> 2.2.0) - gitlab_quality-test_tooling (~> 1.12.0) + gitlab_quality-test_tooling (~> 1.13.0) gon (~> 6.4.0) google-apis-androidpublisher_v3 (~> 0.34.0) google-apis-cloudbilling_v1 (~> 0.21.0) diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 50266e2c434..b5e446d13e4 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -15,6 +15,7 @@ import { MR_COMMITS_PREVIOUS_COMMIT, } from '~/behaviors/shortcuts/keybindings'; import { createAlert } from '~/alert'; +import { InternalEvents } from '~/tracking'; import { isSingleViewStyle } from '~/helpers/diffs_helper'; import { helpPagePath } from '~/helpers/help_page_helper'; import { parseBoolean, handleLocationHash } from '~/lib/utils/common_utils'; @@ -86,7 +87,7 @@ export default { GlSprintf, GlAlert, }, - mixins: [glFeatureFlagsMixin()], + mixins: [glFeatureFlagsMixin(), InternalEvents.mixin()], alerts: { ALERT_OVERFLOW_HIDDEN, ALERT_MERGE_CONFLICT, @@ -443,6 +444,8 @@ export default { notesEventHub.$once('fetchDiffData', this.fetchData); notesEventHub.$on('refetchDiffData', this.refetchDiffData); notesEventHub.$on('fetchedNotesData', this.rereadNoteHash); + notesEventHub.$on('noteFormAddToReview', this.handleReviewTracking); + notesEventHub.$on('noteFormStartReview', this.handleReviewTracking); diffsEventHub.$on('diffFilesModified', this.setDiscussions); diffsEventHub.$on('doneLoadingBatches', this.autoScroll); diffsEventHub.$on(EVT_MR_PREPARED, this.fetchData); @@ -453,6 +456,8 @@ export default { diffsEventHub.$off(EVT_MR_PREPARED, this.fetchData); diffsEventHub.$off('doneLoadingBatches', this.autoScroll); diffsEventHub.$off('diffFilesModified', this.setDiscussions); + notesEventHub.$off('noteFormStartReview', this.handleReviewTracking); + notesEventHub.$off('noteFormAddToReview', this.handleReviewTracking); notesEventHub.$off('fetchedNotesData', this.rereadNoteHash); notesEventHub.$off('refetchDiffData', this.refetchDiffData); notesEventHub.$off('fetchDiffData', this.fetchData); @@ -679,6 +684,16 @@ export default { reloadPage() { window.location.reload(); }, + handleReviewTracking(event) { + const types = { + noteFormStartReview: 'merge_request_click_start_review_on_changes_tab', + noteFormAddToReview: 'merge_request_click_add_to_review_on_changes_tab', + }; + + if (this.shouldShow && types[event.name]) { + this.trackEvent(types[event.name]); + } + }, }, howToMergeDocsPath: helpPagePath('user/project/merge_requests/reviews/index.md', { anchor: 'checkout-merge-requests-locally-through-the-head-ref', diff --git a/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js index 6484fcff769..9bb2884e065 100644 --- a/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js +++ b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js @@ -401,6 +401,8 @@ export const nWeeksBefore = (date, numberOfWeeks, options) => /** * Returns the date `n` years after the date provided. + * When Feb 29 is the specified date, the default behaviour is to return March 1. + * But to align with the equivalent rails code, moment JS and datefns we should return Feb 28 instead. * * @param {Date} date the initial date * @param {Number} numberOfYears number of years after @@ -408,7 +410,16 @@ export const nWeeksBefore = (date, numberOfWeeks, options) => */ export const nYearsAfter = (date, numberOfYears) => { const clone = newDate(date); - clone.setFullYear(clone.getFullYear() + numberOfYears); + clone.setUTCMonth(clone.getUTCMonth()); + + // If the date we are calculating from is Feb 29, return the equivalent result for Feb 28 + if (clone.getUTCMonth() === 1 && clone.getUTCDate() === 29) { + clone.setUTCDate(28); + } else { + clone.setUTCDate(clone.getUTCDate()); + } + + clone.setUTCFullYear(clone.getUTCFullYear() + numberOfYears); return clone; }; diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 87b55b19c08..17eded3bec0 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -12,6 +12,7 @@ import { slugifyWithUnderscore, } from '~/lib/utils/text_utility'; import { sprintf } from '~/locale'; +import { InternalEvents } from '~/tracking'; import { badgeState } from '~/merge_requests/components/merge_request_header.vue'; import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; @@ -48,7 +49,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - mixins: [issuableStateMixin], + mixins: [issuableStateMixin, InternalEvents.mixin()], props: { noteableType: { type: String, @@ -253,6 +254,10 @@ export default { this.isSubmitting = true; + if (isDraft) { + eventHub.$emit('noteFormAddToReview', { name: 'noteFormAddToReview' }); + } + trackSavedUsingEditor( this.$refs.markdownEditor.isContentEditorActive, `${this.noteableType}_${this.noteType}`, diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 77ce5ea5910..135d595aae5 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -320,12 +320,14 @@ export default { ); }, handleAddToReview() { + const clickType = this.hasDrafts ? 'noteFormAddToReview' : 'noteFormStartReview'; // check if draft should resolve thread const shouldResolve = (this.discussionResolved && !this.isUnresolving) || (!this.discussionResolved && this.isResolving); this.isSubmitting = true; + eventHub.$emit(clickType, { name: clickType }); this.$emit( 'handleFormUpdateAddToReview', this.updatedNoteBody, diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 86f93ee425e..eb6764a7937 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -2,6 +2,7 @@ // eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions } from 'vuex'; import { v4 as uuidv4 } from 'uuid'; +import { InternalEvents } from '~/tracking'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; @@ -39,7 +40,7 @@ export default { TimelineEntryItem, AiSummary: () => import('ee_component/notes/components/ai_summary.vue'), }, - mixins: [glFeatureFlagsMixin()], + mixins: [glFeatureFlagsMixin(), InternalEvents.mixin()], provide() { return { summarizeClientSubscriptionId: uuidv4(), @@ -165,6 +166,9 @@ export default { }); } + eventHub.$on('noteFormAddToReview', this.handleReviewTracking); + eventHub.$on('noteFormStartReview', this.handleReviewTracking); + window.addEventListener('hashchange', this.handleHashChanged); eventHub.$on('notesApp.updateIssuableConfidentiality', this.setConfidentiality); @@ -177,6 +181,8 @@ export default { beforeDestroy() { window.removeEventListener('hashchange', this.handleHashChanged); eventHub.$off('notesApp.updateIssuableConfidentiality', this.setConfidentiality); + eventHub.$off('noteFormStartReview', this.handleReviewTracking); + eventHub.$off('noteFormAddToReview', this.handleReviewTracking); }, methods: { ...mapActions([ @@ -222,6 +228,16 @@ export default { setAiLoading(loading) { this.aiLoading = loading; }, + handleReviewTracking(event) { + const types = { + noteFormStartReview: 'merge_request_click_start_review_on_overview_tab', + noteFormAddToReview: 'merge_request_click_add_to_review_on_overview_tab', + }; + + if (this.shouldShow && window.mrTabs && types[event.name]) { + this.trackEvent(types[event.name]); + } + }, }, systemNote: constants.SYSTEM_NOTE, }; diff --git a/app/assets/javascripts/usage_quotas/storage/components/namespace_storage_app.vue b/app/assets/javascripts/usage_quotas/storage/components/namespace_storage_app.vue index a812b90e378..1594e125da3 100644 --- a/app/assets/javascripts/usage_quotas/storage/components/namespace_storage_app.vue +++ b/app/assets/javascripts/usage_quotas/storage/components/namespace_storage_app.vue @@ -1,20 +1,23 @@ @@ -103,7 +142,26 @@ export default { " /> - + +
+ +
diff --git a/app/assets/javascripts/usage_quotas/storage/components/project_list.vue b/app/assets/javascripts/usage_quotas/storage/components/project_list.vue new file mode 100644 index 00000000000..c6f9b1fff03 --- /dev/null +++ b/app/assets/javascripts/usage_quotas/storage/components/project_list.vue @@ -0,0 +1,208 @@ + + + diff --git a/app/assets/javascripts/usage_quotas/storage/components/storage_type_help_link.vue b/app/assets/javascripts/usage_quotas/storage/components/storage_type_help_link.vue new file mode 100644 index 00000000000..c25b1848124 --- /dev/null +++ b/app/assets/javascripts/usage_quotas/storage/components/storage_type_help_link.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/services/service_ping/submit_service.rb b/app/services/service_ping/submit_service.rb index 72d0c022609..7243bc411f7 100644 --- a/app/services/service_ping/submit_service.rb +++ b/app/services/service_ping/submit_service.rb @@ -16,7 +16,7 @@ module ServicePing end def execute - return unless ServicePing::ServicePingSettings.product_intelligence_enabled? + return unless ServicePing::ServicePingSettings.enabled_and_consented? start_time = Time.current diff --git a/config/events/merge_request_click_add_to_review_on_changes_tab.yml b/config/events/merge_request_click_add_to_review_on_changes_tab.yml new file mode 100644 index 00000000000..5d504b617a0 --- /dev/null +++ b/config/events/merge_request_click_add_to_review_on_changes_tab.yml @@ -0,0 +1,20 @@ +--- +description: User clicks the "Add to review" button on the Merge Request Changes tab +category: InternalEventTracking +action: merge_request_click_add_to_review_on_changes_tab +identifiers: +- project +- namespace +- user +product_section: dev +product_stage: create +product_group: code_review +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/merge_request_click_add_to_review_on_overview_tab.yml b/config/events/merge_request_click_add_to_review_on_overview_tab.yml new file mode 100644 index 00000000000..0001aada7b4 --- /dev/null +++ b/config/events/merge_request_click_add_to_review_on_overview_tab.yml @@ -0,0 +1,20 @@ +--- +description: User clicks the "Add to review" button on the Merge Request Overview tab +category: InternalEventTracking +action: merge_request_click_add_to_review_on_overview_tab +identifiers: +- project +- namespace +- user +product_section: dev +product_stage: create +product_group: code_review +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/merge_request_click_start_review_on_changes_tab.yml b/config/events/merge_request_click_start_review_on_changes_tab.yml new file mode 100644 index 00000000000..a1cd6c0bda3 --- /dev/null +++ b/config/events/merge_request_click_start_review_on_changes_tab.yml @@ -0,0 +1,20 @@ +--- +description: User clicks the "Start a review" button on the Merge Request Changes tab +category: InternalEventTracking +action: merge_request_click_start_review_on_changes_tab +identifiers: +- project +- namespace +- user +product_section: dev +product_stage: create +product_group: code_review +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/merge_request_click_start_review_on_overview_tab.yml b/config/events/merge_request_click_start_review_on_overview_tab.yml new file mode 100644 index 00000000000..ec7be2a6c1e --- /dev/null +++ b/config/events/merge_request_click_start_review_on_overview_tab.yml @@ -0,0 +1,20 @@ +--- +description: User clicks the "Start a review" button on the Merge Request Overview tab +category: InternalEventTracking +action: merge_request_click_start_review_on_overview_tab +identifiers: +- project +- namespace +- user +product_section: dev +product_stage: create +product_group: code_review +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/feature_flags/gitlab_com_derisk/github_importer_attachments.yml b/config/feature_flags/gitlab_com_derisk/github_importer_attachments.yml deleted file mode 100644 index ab068225d2c..00000000000 --- a/config/feature_flags/gitlab_com_derisk/github_importer_attachments.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: github_importer_attachments -feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/436400 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140524 -rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17318 -milestone: '16.8' -group: group::import and integrate -type: gitlab_com_derisk -default_enabled: false diff --git a/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_changes_tab_monthly.yml b/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_changes_tab_monthly.yml new file mode 100644 index 00000000000..160258d006e --- /dev/null +++ b/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_changes_tab_monthly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_changes_tab_monthly +description: Monthly count of clicks on the Add to review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_changes_tab +events: +- name: merge_request_click_add_to_review_on_changes_tab diff --git a/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_overview_tab_monthly.yml b/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_overview_tab_monthly.yml new file mode 100644 index 00000000000..8f6942d62e7 --- /dev/null +++ b/config/metrics/counts_28d/count_total_merge_request_click_add_to_review_on_overview_tab_monthly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_overview_tab_monthly +description: Monthly count of clicks on the Add to review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_overview_tab +events: +- name: merge_request_click_add_to_review_on_overview_tab diff --git a/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_changes_tab_monthly.yml b/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_changes_tab_monthly.yml new file mode 100644 index 00000000000..8b769405979 --- /dev/null +++ b/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_changes_tab_monthly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_changes_tab_monthly +description: Monthly count of clicks on the Start a Review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_changes_tab +events: +- name: merge_request_click_start_review_on_changes_tab diff --git a/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_overview_tab_monthly.yml b/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_overview_tab_monthly.yml new file mode 100644 index 00000000000..203cd468f3d --- /dev/null +++ b/config/metrics/counts_28d/count_total_merge_request_click_start_review_on_overview_tab_monthly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_overview_tab_monthly +description: Monthly count of clicks on the Start a Review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_overview_tab +events: +- name: merge_request_click_start_review_on_overview_tab diff --git a/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_changes_tab_weekly.yml b/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_changes_tab_weekly.yml new file mode 100644 index 00000000000..d764a377dc5 --- /dev/null +++ b/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_changes_tab_weekly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_changes_tab_weekly +description: Weekly count of clicks on the Add to review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_changes_tab +events: +- name: merge_request_click_add_to_review_on_changes_tab diff --git a/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_overview_tab_weekly.yml b/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_overview_tab_weekly.yml new file mode 100644 index 00000000000..c11ac48986e --- /dev/null +++ b/config/metrics/counts_7d/count_total_merge_request_click_add_to_review_on_overview_tab_weekly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_overview_tab_weekly +description: Weekly count of clicks on the Add to review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_overview_tab +events: +- name: merge_request_click_add_to_review_on_overview_tab diff --git a/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_changes_tab_weekly.yml b/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_changes_tab_weekly.yml new file mode 100644 index 00000000000..0fdf6762da1 --- /dev/null +++ b/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_changes_tab_weekly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_changes_tab_weekly +description: Weekly count of clicks on the Start a Review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_changes_tab +events: +- name: merge_request_click_start_review_on_changes_tab diff --git a/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_overview_tab_weekly.yml b/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_overview_tab_weekly.yml new file mode 100644 index 00000000000..4ff3f9b090c --- /dev/null +++ b/config/metrics/counts_7d/count_total_merge_request_click_start_review_on_overview_tab_weekly.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_overview_tab_weekly +description: Weekly count of clicks on the Start a Review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_overview_tab +events: +- name: merge_request_click_start_review_on_overview_tab diff --git a/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_changes_tab.yml b/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_changes_tab.yml new file mode 100644 index 00000000000..0383f854a4e --- /dev/null +++ b/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_changes_tab.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_changes_tab +description: Total count of clicks on the Add to review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: all +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_changes_tab +events: +- name: merge_request_click_add_to_review_on_changes_tab diff --git a/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_overview_tab.yml b/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_overview_tab.yml new file mode 100644 index 00000000000..e9ed2d5c155 --- /dev/null +++ b/config/metrics/counts_all/count_total_merge_request_click_add_to_review_on_overview_tab.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_add_to_review_on_overview_tab +description: Total count of clicks on the Add to review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: all +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_add_to_review_on_overview_tab +events: +- name: merge_request_click_add_to_review_on_overview_tab diff --git a/config/metrics/counts_all/count_total_merge_request_click_start_review_on_changes_tab.yml b/config/metrics/counts_all/count_total_merge_request_click_start_review_on_changes_tab.yml new file mode 100644 index 00000000000..bac1dbbc1cb --- /dev/null +++ b/config/metrics/counts_all/count_total_merge_request_click_start_review_on_changes_tab.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_changes_tab +description: Total count of clicks on the Start a Review button on the MR Changes tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: all +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_changes_tab +events: +- name: merge_request_click_start_review_on_changes_tab diff --git a/config/metrics/counts_all/count_total_merge_request_click_start_review_on_overview_tab.yml b/config/metrics/counts_all/count_total_merge_request_click_start_review_on_overview_tab.yml new file mode 100644 index 00000000000..7ee5058c7ca --- /dev/null +++ b/config/metrics/counts_all/count_total_merge_request_click_start_review_on_overview_tab.yml @@ -0,0 +1,26 @@ +--- +key_path: counts.count_total_merge_request_click_start_review_on_overview_tab +description: Total count of clicks on the Start a Review button on the MR Overview tab +product_section: dev +product_stage: create +product_group: code_review +performance_indicator_type: [] +value_type: number +status: active +milestone: '16.9' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141911 +time_frame: all +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +options: + events: + - merge_request_click_start_review_on_overview_tab +events: +- name: merge_request_click_start_review_on_overview_tab diff --git a/doc/api/resource_state_events.md b/doc/api/resource_state_events.md index 1c8f743ca72..c2b2c80883a 100644 --- a/doc/api/resource_state_events.md +++ b/doc/api/resource_state_events.md @@ -13,6 +13,9 @@ Resource state events keep track of what happens to GitLab [issues](../user/proj Use them to track which state was set, who did it, and when it happened. +Resource state events API does not track the initial state ("create" or "open") of resources. +For a resource that was not closed or re-opened, an empty list is returned. + ## Issues ### List project issue state events diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md index 66bb662e1c7..ddddeca8168 100644 --- a/doc/development/documentation/restful_api_styleguide.md +++ b/doc/development/documentation/restful_api_styleguide.md @@ -32,9 +32,8 @@ In the Markdown doc for a resource (AKA endpoint): - Every method must have a detailed [description of the response body](#response-body-description). - Every method must have a response body example (in JSON format). - If an attribute is available only to higher level tiers than the other - attributes, add the appropriate inline [tier badge](styleguide/index.md#product-tier-badges). - Put the badge in the **Attribute** column, like the - `**()**` code in the following template. + attributes, add the appropriate tier to the description. If an attribute is + for Premium, include that it's also available for Ultimate. After a new API documentation page is added, [add an entry in the global navigation](site_architecture/global_nav.md#add-a-navigation-entry). [Example](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/3497). @@ -65,7 +64,7 @@ Supported attributes: | Attribute | Type | Required | Description | |--------------------------|----------|----------|-----------------------| | `attribute` | datatype | Yes | Detailed description. | -| `attribute` **()** | datatype | No | Detailed description. | +| `attribute` | datatype | No | Detailed description. | | `attribute` | datatype | No | Detailed description. | | `attribute` | datatype | No | Detailed description. | @@ -75,7 +74,7 @@ response attributes: | Attribute | Type | Description | |--------------------------|----------|-----------------------| | `attribute` | datatype | Detailed description. | -| `attribute` **()** | datatype | Detailed description. | +| `attribute` | datatype | Detailed description. | Example request: @@ -146,7 +145,7 @@ Sort the table by required attributes first, then alphabetically. | Attribute | Type | Required | Description | |------------------------------|---------------|----------|-----------------------------------------------------| | `title` | string | Yes | Title of the issue. | -| `assignee_ids` **(PREMIUM ALL)** | integer array | No | IDs of the users to assign the issue to. | +| `assignee_ids` | integer array | No | IDs of the users to assign the issue to. Ultimate only. | | `confidential` | boolean | No | Sets the issue to confidential. Default is `false`. | ``` @@ -155,7 +154,7 @@ Rendered example: | Attribute | Type | Required | Description | |------------------------------|---------------|----------|-----------------------------------------------------| | `title` | string | Yes | Title of the issue. | -| `assignee_ids` **(PREMIUM ALL)** | integer array | No | IDs of the users to assign the issue to. | +| `assignee_ids` | integer array | No | IDs of the users to assign the issue to. Premium and Ultimate only. | | `confidential` | boolean | No | Sets the issue to confidential. Default is `false`. | For information about writing attribute descriptions, see the [GraphQL API description style guide](../api_graphql_styleguide.md#description-style-guide). @@ -181,7 +180,7 @@ Sort the table alphabetically. ```markdown | Attribute | Type | Description | |------------------------------|---------------|-------------------------------------------| -| `assignee_ids` **(PREMIUM ALL)** | integer array | IDs of the users to assign the issue to. | +| `assignee_ids` | integer array | IDs of the users to assign the issue to. Premium and Ultimate only. | | `confidential` | boolean | Whether the issue is confidential or not. | | `title` | string | Title of the issue. | ``` @@ -190,7 +189,7 @@ Rendered example: | Attribute | Type | Description | |------------------------------|---------------|-------------------------------------------| -| `assignee_ids` **(PREMIUM ALL)** | integer array | IDs of the users to assign the issue to. | +| `assignee_ids` | integer array | IDs of the users to assign the issue to. Premium and Ultimate only. | | `confidential` | boolean | Whether the issue is confidential or not. | | `title` | string | Title of the issue. | diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index a41390558ad..4f812712651 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -1648,7 +1648,7 @@ Tier badges provide information about a feature and are displayed next to the to Assign tier badges to: -- All H1 topic titles, except the pages under `doc/development/*` and `doc/solutions/*`. +- Most H1 topic titles, except the pages under `doc/development/*` and `doc/solutions/*`. - Topic titles that don't apply to the same tier as the H1. The H1 tier badge should be the badge that applies to the lowest tier for the features on the page. @@ -1731,10 +1731,19 @@ Or add the status by itself: ##### Inline tier badges -Do not add tier badges inline with other text, except for [API attributes](../restful_api_styleguide.md). +Do not add tier badges inline with other text. The single source of truth for a feature should be the topic where the functionality is described. +If you need to mention a tier inline, write it in plain text. For example, +for an API topic: + +```markdown +IDs of the users to assign the issue to. Ultimate only. +``` + +For more examples, see the [REST API style guide](../restful_api_styleguide.md). + ##### Administrator documentation tier badges Topics that are only for instance administrators should be badged ` SELF`. Instance diff --git a/doc/user/ai_features.md b/doc/user/ai_features.md index 3e55661d00f..0891ae20918 100644 --- a/doc/user/ai_features.md +++ b/doc/user/ai_features.md @@ -14,22 +14,22 @@ GitLab is creating AI-assisted features across our DevSecOps platform. These fea | Goal | Feature | Tier/Offering/Status | |---|---|---| -| Helps you discover or recall Git commands when and where you need them. | [Git suggestions](https://gitlab.com/gitlab-org/gitlab/-/issues/409636) | **(ULTIMATE SAAS EXPERIMENT)** | -| Assists with quickly getting everyone up to speed on lengthy conversations to help ensure you are all on the same page. | [Discussion summary](#summarize-issue-discussions-with-discussion-summary) | **(ULTIMATE SAAS EXPERIMENT)** | -| Generates issue descriptions. | [Issue description generation](#summarize-an-issue-with-issue-description-generation) | **(ULTIMATE SAAS EXPERIMENT)** | -| Helps you write code more efficiently by viewing code suggestions as you type.

[Watch overview](https://www.youtube.com/watch?v=hCAyCTacdAQ) | [Code Suggestions](project/repository/code_suggestions/index.md) | For SaaS: **(FREE)**

For self-managed: **(PREMIUM)** | -| Automates repetitive tasks and helps catch bugs early. | [Test generation](gitlab_duo_chat.md#write-tests-in-the-ide) | **(ULTIMATE BETA)** | -| Generates a description for the merge request based on the contents of the template. | [Merge request template population](project/merge_requests/ai_in_merge_requests.md#fill-in-merge-request-templates) | **(ULTIMATE SAAS EXPERIMENT)** | -| Assists in creating faster and higher-quality reviews by automatically suggesting reviewers for your merge request.

[Watch overview](https://www.youtube.com/watch?v=ivwZQgh4Rxw) | [Suggested Reviewers](project/merge_requests/reviews/index.md#gitlab-duo-suggested-reviewers) | **(ULTIMATE SAAS)** | -| Efficiently communicates the impact of your merge request changes. | [Merge request summary](project/merge_requests/ai_in_merge_requests.md#summarize-merge-request-changes) | **(ULTIMATE SAAS EXPERIMENT)** | -| Helps ease merge request handoff between authors and reviewers and help reviewers efficiently understand suggestions. | [Code review summary](project/merge_requests/ai_in_merge_requests.md#summarize-my-merge-request-review) | **(ULTIMATE SAAS EXPERIMENT)** | -| Helps you remediate vulnerabilities more efficiently, boost your skills, and write more secure code.

[Watch overview](https://www.youtube.com/watch?v=6sDf73QOav8) | [Vulnerability summary](application_security/vulnerabilities/index.md#explaining-a-vulnerability) | **(ULTIMATE SAAS BETA)** | -| Generates a merge request containing the changes required to mitigate a vulnerability. | [Vulnerability resolution](application_security/vulnerabilities/index.md#explaining-a-vulnerability) | **(ULTIMATE SAAS EXPERIMENT)** | -| Helps you understand code by explaining it in English language.

[Watch overview](https://www.youtube.com/watch?v=1izKaLmmaCA) | [Code explanation](#explain-code-in-the-web-ui-with-code-explanation) | **(ULTIMATE SAAS EXPERIMENT)** | -| Processes and generates text and code in a conversational manner. Helps you quickly identify useful information in large volumes of text in issues, epics, code, and GitLab documentation. | [GitLab Duo Chat](gitlab_duo_chat.md) | **(ULTIMATE ALL BETA)** | -| Assists you in determining the root cause for a pipeline failure and failed CI/CD build. | [Root cause analysis](#root-cause-analysis) | **(ULTIMATE SAAS EXPERIMENT)** | -| Assists you with predicting productivity metrics and identifying anomalies across your software development lifecycle. | [Value stream forecasting](#forecast-deployment-frequency-with-value-stream-forecasting) | **(ULTIMATE ALL EXPERIMENT)** | -| Processes and responds to your questions about your application's usage data. | [Product Analytics](product_analytics/index.md) | **(ULTIMATE SAAS EXPERIMENT)** | +| Helps you discover or recall Git commands when and where you need them. | [Git suggestions](https://gitlab.com/gitlab-org/gitlab/-/issues/409636) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Assists with quickly getting everyone up to speed on lengthy conversations to help ensure you are all on the same page. | [Discussion summary](#summarize-issue-discussions-with-discussion-summary) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Generates issue descriptions. | [Issue description generation](#summarize-an-issue-with-issue-description-generation) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Helps you write code more efficiently by viewing code suggestions as you type.

[Watch overview](https://www.youtube.com/watch?v=hCAyCTacdAQ) | [Code Suggestions](project/repository/code_suggestions/index.md) | **Offering:** SaaS **Tier:** Free

**Offering:** Self-managed **Tier:** Premium and Ultimate | +| Automates repetitive tasks and helps catch bugs early. | [Test generation](gitlab_duo_chat.md#write-tests-in-the-ide) | **Tier:** Ultimate
**Offering:** SaaS, self-managed
**Status:** Beta | +| Generates a description for the merge request based on the contents of the template. | [Merge request template population](project/merge_requests/ai_in_merge_requests.md#fill-in-merge-request-templates) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Assists in creating faster and higher-quality reviews by automatically suggesting reviewers for your merge request.

[Watch overview](https://www.youtube.com/watch?v=ivwZQgh4Rxw) | [Suggested Reviewers](project/merge_requests/reviews/index.md#gitlab-duo-suggested-reviewers) | **Tier:** Ultimate
**Offering:** SaaS | +| Efficiently communicates the impact of your merge request changes. | [Merge request summary](project/merge_requests/ai_in_merge_requests.md#summarize-merge-request-changes) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Helps ease merge request handoff between authors and reviewers and help reviewers efficiently understand suggestions. | [Code review summary](project/merge_requests/ai_in_merge_requests.md#summarize-my-merge-request-review) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Helps you remediate vulnerabilities more efficiently, boost your skills, and write more secure code.

[Watch overview](https://www.youtube.com/watch?v=6sDf73QOav8) | [Vulnerability summary](application_security/vulnerabilities/index.md#explaining-a-vulnerability) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Beta | +| Generates a merge request containing the changes required to mitigate a vulnerability. | [Vulnerability resolution](application_security/vulnerabilities/index.md#explaining-a-vulnerability) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Helps you understand code by explaining it in English language.

[Watch overview](https://www.youtube.com/watch?v=1izKaLmmaCA) | [Code explanation](#explain-code-in-the-web-ui-with-code-explanation) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Processes and generates text and code in a conversational manner. Helps you quickly identify useful information in large volumes of text in issues, epics, code, and GitLab documentation. | [GitLab Duo Chat](gitlab_duo_chat.md) | **Tier:** Ultimate
**Offering:** SaaS, self-managed
**Status:** Beta | +| Assists you in determining the root cause for a pipeline failure and failed CI/CD build. | [Root cause analysis](#root-cause-analysis) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | +| Assists you with predicting productivity metrics and identifying anomalies across your software development lifecycle. | [Value stream forecasting](#forecast-deployment-frequency-with-value-stream-forecasting) | **Tier:** Ultimate
**Offering:** SaaS, self-managed
**Status:** Experiment | +| Processes and responds to your questions about your application's usage data. | [Product Analytics](product_analytics/index.md) | **Tier:** Ultimate
**Offering:** SaaS
**Status:** Experiment | ## Enable AI/ML features diff --git a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb index 68d511b065f..429a28dcb4c 100644 --- a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb +++ b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb @@ -22,7 +22,12 @@ module BulkImports wiki = context.portable.wiki url = data[:url].sub("://", "://oauth2:#{context.configuration.access_token}@") - Gitlab::UrlBlocker.validate!(url, schemes: %w[http https], allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?) + Gitlab::HTTP_V2::UrlBlocker.validate!( + url, + schemes: %w[http https], + allow_local_network: allow_local_requests?, + allow_localhost: allow_local_requests?, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?) wiki.create_wiki_repository wiki.repository.fetch_as_mirror(url) diff --git a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb index a2b1f8c5176..04c887441f4 100644 --- a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb +++ b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb @@ -21,7 +21,12 @@ module BulkImports url = url.sub("://", "://oauth2:#{context.configuration.access_token}@") project = context.portable - Gitlab::UrlBlocker.validate!(url, schemes: %w[http https], allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?) + Gitlab::HTTP_V2::UrlBlocker.validate!( + url, + schemes: %w[http https], + allow_local_network: allow_local_requests?, + allow_localhost: allow_local_requests?, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?) project.ensure_repository project.repository.fetch_as_mirror(url) diff --git a/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb b/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb index 39c9c121797..a371c33d9ea 100644 --- a/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb +++ b/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb @@ -53,10 +53,11 @@ module BulkImports end def validate_url(url) - Gitlab::UrlBlocker.validate!( + Gitlab::HTTP_V2::UrlBlocker.validate!( url, allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?, schemes: %w[http https] ) end diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index 6222155d812..a771cf24db9 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -33,7 +33,7 @@ module Gitlab MAX_TEXT_SIZE_LIMIT = 1_000_000 # Migrations before this version may have been removed - MIN_SCHEMA_GITLAB_VERSION = '15.11' + MIN_SCHEMA_GITLAB_VERSION = '16.7' # Schema we store dynamically managed partitions in (e.g. for time partitioning) DYNAMIC_PARTITIONS_SCHEMA = :gitlab_partitions_dynamic diff --git a/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb b/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb index 3b0b4c6e935..9b9b0f65633 100644 --- a/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb +++ b/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb @@ -232,7 +232,11 @@ module Gitlab url = Gitlab::CurrentSettings.current_application_settings.error_tracking_api_url || 'http://localhost:8080' - Gitlab::UrlBlocker.validate!(url, schemes: %w[http https], allow_localhost: true) + Gitlab::HTTP_V2::UrlBlocker.validate!( + url, + schemes: %w[http https], + allow_localhost: true, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?) URI(url) end diff --git a/lib/gitlab/github_gists_import/importer/gist_importer.rb b/lib/gitlab/github_gists_import/importer/gist_importer.rb index 71dfe5e2aa5..c2456f83711 100644 --- a/lib/gitlab/github_gists_import/importer/gist_importer.rb +++ b/lib/gitlab/github_gists_import/importer/gist_importer.rb @@ -58,11 +58,13 @@ module Gitlab end def get_resolved_address - validated_pull_url, host = Gitlab::UrlBlocker.validate!(gist.git_pull_url, - schemes: Project::VALID_IMPORT_PROTOCOLS, - ports: Project::VALID_IMPORT_PORTS, - allow_localhost: allow_local_requests?, - allow_local_network: allow_local_requests?) + validated_pull_url, host = Gitlab::HTTP_V2::UrlBlocker.validate!( + gist.git_pull_url, + schemes: Project::VALID_IMPORT_PROTOCOLS, + ports: Project::VALID_IMPORT_PORTS, + allow_localhost: allow_local_requests?, + allow_local_network: allow_local_requests?, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?) host.present? ? validated_pull_url.host.to_s : '' end diff --git a/lib/gitlab/github_import/importer/attachments/base_importer.rb b/lib/gitlab/github_import/importer/attachments/base_importer.rb index 844008f8087..9dfa6bb2ff6 100644 --- a/lib/gitlab/github_import/importer/attachments/base_importer.rb +++ b/lib/gitlab/github_import/importer/attachments/base_importer.rb @@ -52,8 +52,6 @@ module Gitlab end def has_attachments?(object) - return true if Feature.disabled?(:github_importer_attachments, project, type: :gitlab_com_derisk) - object_representation(object).has_attachments? end end diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb index 44e53e9ec70..593090902e7 100644 --- a/lib/gitlab/kubernetes/kube_client.rb +++ b/lib/gitlab/kubernetes/kube_client.rb @@ -161,7 +161,11 @@ module Gitlab def validate_url! return if Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? - Gitlab::UrlBlocker.validate!(api_prefix, allow_local_network: false, schemes: %w[http https]) + Gitlab::HTTP_V2::UrlBlocker.validate!( + api_prefix, + allow_local_network: false, + schemes: %w[http https], + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?) end def service_account_exists?(resource) diff --git a/lib/gitlab/octokit/middleware.rb b/lib/gitlab/octokit/middleware.rb index f944f9827a3..a93526da5ca 100644 --- a/lib/gitlab/octokit/middleware.rb +++ b/lib/gitlab/octokit/middleware.rb @@ -8,11 +8,12 @@ module Gitlab end def call(env) - Gitlab::UrlBlocker.validate!(env[:url], + Gitlab::HTTP_V2::UrlBlocker.validate!(env[:url], schemes: %w[http https], allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests?, - dns_rebind_protection: dns_rebind_protection? + dns_rebind_protection: dns_rebind_protection?, + deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed? ) @app.call(env) diff --git a/lib/service_ping/service_ping_settings.rb b/lib/service_ping/service_ping_settings.rb index 6964210b1db..8c99f1138c5 100644 --- a/lib/service_ping/service_ping_settings.rb +++ b/lib/service_ping/service_ping_settings.rb @@ -4,7 +4,7 @@ module ServicePing module ServicePingSettings extend self - def product_intelligence_enabled? + def enabled_and_consented? enabled? && !User.single_user&.requires_usage_stats_consent? end diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 5e0dfd8bd09..0d25057993a 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -8,6 +8,7 @@ import Vuex from 'vuex'; import getMRCodequalityAndSecurityReports from '~/diffs/components/graphql/get_mr_codequality_and_security_reports.query.graphql'; import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; +import { mockTracking } from 'helpers/tracking_helper'; import { TEST_HOST } from 'spec/test_constants'; import App from '~/diffs/components/app.vue'; @@ -22,6 +23,7 @@ import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vu import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue'; import eventHub from '~/diffs/event_hub'; +import notesEventHub from '~/notes/event_hub'; import { EVT_DISCUSSIONS_ASSIGNED } from '~/diffs/constants'; import axios from '~/lib/utils/axios_utils'; @@ -888,4 +890,38 @@ describe('diffs/components/app', () => { expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); }); }); + + describe('draft comments', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking(undefined, window.document, jest.spyOn); + }); + + describe('when adding a new comment to an existing review', () => { + it('sends the correct tracking event', () => { + createComponent({ shouldShow: true }); + notesEventHub.$emit('noteFormAddToReview', { name: 'noteFormAddToReview' }); + + expect(trackingSpy).toHaveBeenCalledWith( + undefined, + 'merge_request_click_add_to_review_on_changes_tab', + expect.any(Object), + ); + }); + }); + + describe('when adding a comment to a new review', () => { + it('sends the correct tracking event', () => { + createComponent({ shouldShow: true }); + notesEventHub.$emit('noteFormStartReview', { name: 'noteFormStartReview' }); + + expect(trackingSpy).toHaveBeenCalledWith( + undefined, + 'merge_request_click_start_review_on_changes_tab', + expect.any(Object), + ); + }); + }); + }); }); diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js index 73a4af2c85d..5027c924e63 100644 --- a/spec/frontend/lib/utils/datetime_utility_spec.js +++ b/spec/frontend/lib/utils/datetime_utility_spec.js @@ -785,11 +785,16 @@ describe('date addition/subtraction methods', () => { ); }); + // NOTE: 2024-02-29 is a leap day describe('nYearsAfter', () => { it.each` date | numberOfYears | expected ${'2020-07-06'} | ${1} | ${'2021-07-06'} ${'2020-07-06'} | ${15} | ${'2035-07-06'} + ${'2024-03-02'} | ${1} | ${'2025-03-02'} + ${'2024-03-01'} | ${1} | ${'2025-03-01'} + ${'2024-02-29'} | ${1} | ${'2025-02-28'} + ${'2024-02-28'} | ${1} | ${'2025-02-28'} `( 'returns $expected for "$numberOfYears year(s) after $date"', ({ date, numberOfYears, expected }) => { @@ -805,6 +810,10 @@ describe('date addition/subtraction methods', () => { date | numberOfYears | expected ${'2020-07-06'} | ${4} | ${'2016-07-06'} ${'2020-07-06'} | ${1} | ${'2019-07-06'} + ${'2024-03-02'} | ${1} | ${'2023-03-02'} + ${'2024-03-01'} | ${1} | ${'2023-03-01'} + ${'2024-02-29'} | ${1} | ${'2023-02-28'} + ${'2024-02-28'} | ${1} | ${'2023-02-28'} `( 'returns $expected for "$numberOfYears year(s) before $date"', ({ date, numberOfYears, expected }) => { diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index 8f761476c7c..500032eac26 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -401,11 +401,28 @@ describe('issue_comment_form component', () => { let store; beforeEach(() => { - store = createStore(); + store = createStore({ + actions: { + saveNote: jest.fn().mockResolvedValue(), + }, + }); store.registerModule('batchComments', batchComments()); store.state.batchComments.drafts = [{ note: 'A' }]; }); + it('sends the event to indicate that a new draft comment has been added', () => { + const note = 'some note text which enables actually adding a draft note'; + + jest.spyOn(eventHub, '$emit'); + mountComponent({ mountFunction: mount, initialData: { note }, store }); + + findAddToReviewButton().trigger('click'); + + expect(eventHub.$emit).toHaveBeenCalledWith('noteFormAddToReview', { + name: 'noteFormAddToReview', + }); + }); + it('should save note draft when cmd+enter is pressed', async () => { mountComponent({ mountFunction: mount, store }); jest.spyOn(wrapper.vm, 'handleSaveDraft'); diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js index e2072ebd04d..dad36a290b1 100644 --- a/spec/frontend/notes/components/note_form_spec.js +++ b/spec/frontend/notes/components/note_form_spec.js @@ -7,6 +7,7 @@ import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import CommentFieldLayout from '~/notes/components/comment_field_layout.vue'; import { AT_WHO_ACTIVE_CLASS } from '~/gfm_auto_complete'; import eventHub from '~/environments/event_hub'; +import notesEventHub from '~/notes/event_hub'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import { mockTracking } from 'helpers/tracking_helper'; import { noteableDataMock, notesDataMock, discussionMock, note } from '../mock_data'; @@ -16,6 +17,7 @@ jest.mock('~/lib/utils/autosave'); describe('issue_note_form component', () => { let store; let wrapper; + let textarea; let props; let trackingSpy; @@ -39,10 +41,13 @@ describe('issue_note_form component', () => { }, }, }); + + textarea = wrapper.find('textarea'); }; const findCancelButton = () => wrapper.findByTestId('cancel'); const findCancelCommentButton = () => wrapper.findByTestId('cancelBatchCommentsEnabled'); + const findAddToStartReviewButton = () => wrapper.findByTestId('start-review-button'); const findMarkdownField = () => wrapper.findComponent(MarkdownField); beforeEach(() => { @@ -112,14 +117,10 @@ describe('issue_note_form component', () => { }); it('should render text area with placeholder', () => { - const textarea = wrapper.find('textarea'); - expect(textarea.attributes('placeholder')).toBe('Write a comment or drag your files hereā€¦'); }); it('should set data-supports-quick-actions to enable autocomplete', () => { - const textarea = wrapper.find('textarea'); - expect(textarea.attributes('data-supports-quick-actions')).toBe('true'); }); @@ -147,10 +148,7 @@ describe('issue_note_form component', () => { }); describe('keyboard events', () => { - let textarea; - beforeEach(() => { - textarea = wrapper.find('textarea'); textarea.setValue('Foo'); }); @@ -213,7 +211,6 @@ describe('issue_note_form component', () => { it('should be possible to update the note', () => { createComponentWrapper(); - const textarea = wrapper.find('textarea'); textarea.setValue('Foo'); const saveButton = wrapper.find('.js-vue-issue-save'); saveButton.vm.$emit('click'); @@ -224,7 +221,6 @@ describe('issue_note_form component', () => { it('tracks event when save button is clicked', () => { createComponentWrapper(); - const textarea = wrapper.find('textarea'); textarea.setValue('Foo'); const saveButton = wrapper.find('.js-vue-issue-save'); saveButton.vm.$emit('click'); @@ -313,8 +309,6 @@ describe('issue_note_form component', () => { describe('on enter', () => { it('should start review or add to review when cmd+enter is pressed', async () => { - const textarea = wrapper.find('textarea'); - textarea.setValue('Foo'); textarea.trigger('keydown.enter', { metaKey: true }); @@ -325,5 +319,40 @@ describe('issue_note_form component', () => { ]); }); }); + + describe('when adding a draft comment', () => { + beforeEach(() => { + jest.spyOn(notesEventHub, '$emit'); + }); + + it('sends the event to indicate that a draft has been added to the review', () => { + store.state.batchComments.drafts = [{ note: 'A' }]; + createComponentWrapper({ + isDraft: true, + noteId: '', + discussion: { ...discussionMock, for_commit: false }, + }); + + findAddToStartReviewButton().trigger('click'); + + expect(notesEventHub.$emit).toHaveBeenCalledWith('noteFormAddToReview', { + name: 'noteFormAddToReview', + }); + }); + + it('sends the event to indicate that a review has been started with the new draft', () => { + createComponentWrapper({ + isDraft: true, + noteId: '', + discussion: { ...discussionMock, for_commit: false }, + }); + + findAddToStartReviewButton().trigger('click'); + + expect(notesEventHub.$emit).toHaveBeenCalledWith('noteFormStartReview', { + name: 'noteFormStartReview', + }); + }); + }); }); }); diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index d49ab0d71db..e278d53b55a 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -3,6 +3,7 @@ import AxiosMockAdapter from 'axios-mock-adapter'; import $ from 'jquery'; import { nextTick } from 'vue'; import setWindowLocation from 'helpers/set_window_location_helper'; +import { mockTracking } from 'helpers/tracking_helper'; import waitForPromises from 'helpers/wait_for_promises'; import DraftNote from '~/batch_comments/components/draft_note.vue'; import batchComments from '~/batch_comments/stores/modules/batch_comments'; @@ -10,6 +11,7 @@ import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { getLocationHash } from '~/lib/utils/url_utility'; import * as urlUtility from '~/lib/utils/url_utility'; +import notesEventHub from '~/notes/event_hub'; import CommentForm from '~/notes/components/comment_form.vue'; import NotesApp from '~/notes/components/notes_app.vue'; import NotesActivityHeader from '~/notes/components/notes_activity_header.vue'; @@ -453,4 +455,39 @@ describe('note_app', () => { }); }); }); + + describe('draft comments', () => { + let trackingSpy; + + beforeEach(() => { + window.mrTabs = { eventHub: notesEventHub }; + axiosMock.onAny().reply(mockData.getIndividualNoteResponse); + trackingSpy = mockTracking(undefined, window.document, jest.spyOn); + wrapper = mountComponent(); + }); + + describe('when adding a new comment to an existing review', () => { + it('sends the correct tracking event', () => { + notesEventHub.$emit('noteFormAddToReview', { name: 'noteFormAddToReview' }); + + expect(trackingSpy).toHaveBeenCalledWith( + undefined, + 'merge_request_click_add_to_review_on_overview_tab', + expect.any(Object), + ); + }); + }); + + describe('when adding a comment to a new review', () => { + it('sends the correct tracking event', () => { + notesEventHub.$emit('noteFormStartReview', { name: 'noteFormStartReview' }); + + expect(trackingSpy).toHaveBeenCalledWith( + undefined, + 'merge_request_click_start_review_on_overview_tab', + expect.any(Object), + ); + }); + }); + }); }); diff --git a/spec/frontend/usage_quotas/storage/components/storage_type_help_link_spec.js b/spec/frontend/usage_quotas/storage/components/storage_type_help_link_spec.js new file mode 100644 index 00000000000..9c855e4bec1 --- /dev/null +++ b/spec/frontend/usage_quotas/storage/components/storage_type_help_link_spec.js @@ -0,0 +1,49 @@ +import { GlLink } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import StorageTypeHelpLink from '~/usage_quotas/storage/components/storage_type_help_link.vue'; +import { storageTypeHelpPaths } from '~/usage_quotas/storage/constants'; + +let wrapper; + +const createComponent = ({ props = {} } = {}) => { + wrapper = shallowMount(StorageTypeHelpLink, { + propsData: { + helpLinks: storageTypeHelpPaths, + ...props, + }, + }); +}; + +const findLink = () => wrapper.findComponent(GlLink); + +describe('StorageTypeHelpLink', () => { + describe('Storage type w/ link', () => { + describe.each(Object.entries(storageTypeHelpPaths))('%s', (storageType, url) => { + beforeEach(() => { + createComponent({ + props: { + storageType, + }, + }); + }); + + it('will have proper href', () => { + expect(findLink().attributes('href')).toBe(url); + }); + }); + }); + + describe('Storage type w/o help link', () => { + beforeEach(() => { + createComponent({ + props: { + storageType: 'Yellow Submarine', + }, + }); + }); + + it('will not have a href', () => { + expect(findLink().attributes('href')).toBe(undefined); + }); + }); +}); diff --git a/spec/frontend/usage_quotas/storage/mock_data.js b/spec/frontend/usage_quotas/storage/mock_data.js index e7886614575..3f615f01e17 100644 --- a/spec/frontend/usage_quotas/storage/mock_data.js +++ b/spec/frontend/usage_quotas/storage/mock_data.js @@ -1,6 +1,7 @@ import mockGetProjectStorageStatisticsGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project_storage.query.graphql.json'; import mockGetNamespaceStorageGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/namespace_storage.query.graphql.json'; import mockGetProjectListStorageGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project_list_storage.query.graphql.json'; +import { storageTypeHelpPaths } from '~/usage_quotas/storage/constants'; export { mockGetProjectStorageStatisticsGraphQLResponse }; export { mockGetNamespaceStorageGraphQLResponse }; @@ -15,4 +16,6 @@ export const defaultProjectProvideValues = { export const defaultNamespaceProvideValues = { userNamespace: false, namespaceId: '42', + defaultPerPage: 20, + helpLinks: storageTypeHelpPaths, }; diff --git a/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb b/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb index b098a151660..b64348d447b 100644 --- a/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb +++ b/spec/lib/gitlab/github_gists_import/importer/gist_importer_spec.rb @@ -167,13 +167,16 @@ RSpec.describe Gitlab::GithubGistsImport::Importer::GistImporter, feature_catego before do allow(::Gitlab::CurrentSettings) .to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(true) + allow(::Gitlab::CurrentSettings) + .to receive(:deny_all_requests_except_allowed?).and_return(true) end it 'raises error' do - expect(Gitlab::UrlBlocker) + expect(Gitlab::HTTP_V2::UrlBlocker) .to receive(:validate!) .with(url, ports: [80, 443], schemes: %w[http https git], - allow_localhost: true, allow_local_network: true) + allow_localhost: true, allow_local_network: true, + deny_all_requests_except_allowed: true) .and_raise(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) expect { subject.execute }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) @@ -184,13 +187,16 @@ RSpec.describe Gitlab::GithubGistsImport::Importer::GistImporter, feature_catego before do allow(::Gitlab::CurrentSettings) .to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(false) + allow(::Gitlab::CurrentSettings) + .to receive(:deny_all_requests_except_allowed?).and_return(true) end it 'raises error' do - expect(Gitlab::UrlBlocker) + expect(Gitlab::HTTP_V2::UrlBlocker) .to receive(:validate!) .with(url, ports: [80, 443], schemes: %w[http https git], - allow_localhost: false, allow_local_network: false) + allow_localhost: false, allow_local_network: false, + deny_all_requests_except_allowed: true) .and_raise(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) expect { subject.execute }.to raise_error(Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError) diff --git a/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb index 20152020897..223b7318d69 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb @@ -41,20 +41,6 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::IssuesImporter, feat importer.sequential_import end - context 'when flag is disabled' do - before do - stub_feature_flags(github_importer_attachments: false) - end - - it 'executes importer for both issues' do - expect_next_instances_of(Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2) do |importer| - expect(importer).to receive(:execute) - end - - importer.sequential_import - end - end - context 'when issue has already been processed' do before do importer.mark_as_imported(issue_with_attachment) diff --git a/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb index 5ed6dce8507..5449d4def1f 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb @@ -42,20 +42,6 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporte importer.sequential_import end - context 'when flag is disabled' do - before do - stub_feature_flags(github_importer_attachments: false) - end - - it 'executes importer for both merge requests' do - expect_next_instances_of(Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2) do |importer| - expect(importer).to receive(:execute) - end - - importer.sequential_import - end - end - context 'when merge request has already been processed' do before do importer.mark_as_imported(mr_with_attachment) diff --git a/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb index da0ee1ed0dd..1dfe69ec12d 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb @@ -52,20 +52,6 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::NotesImporter, featu importer.sequential_import end - context 'when flag is disabled' do - before do - stub_feature_flags(github_importer_attachments: false) - end - - it 'executes importer for both user notes' do - expect_next_instances_of(Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2) do |importer| - expect(importer).to receive(:execute) - end - - importer.sequential_import - end - end - context 'when note has already been processed' do before do importer.mark_as_imported(note_with_attachment) diff --git a/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb index cf51760d966..4886cb923dc 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb @@ -41,20 +41,6 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::ReleasesImporter, fe importer.sequential_import end - context 'when flag is disabled' do - before do - stub_feature_flags(github_importer_attachments: false) - end - - it 'executes importer for both releases' do - expect_next_instances_of(Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2) do |importer| - expect(importer).to receive(:execute) - end - - importer.sequential_import - end - end - context 'when release has already been processed' do before do importer.mark_as_imported(release_with_attachment) diff --git a/spec/lib/service_ping/service_ping_settings_spec.rb b/spec/lib/service_ping/service_ping_settings_spec.rb index 040a5027274..2e61b35a131 100644 --- a/spec/lib/service_ping/service_ping_settings_spec.rb +++ b/spec/lib/service_ping/service_ping_settings_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' RSpec.describe ServicePing::ServicePingSettings do using RSpec::Parameterized::TableSyntax - describe '#product_intelligence_enabled?' do - where(:usage_ping_enabled, :requires_usage_stats_consent, :expected_product_intelligence_enabled) do + describe '#enabled_and_consented?' do + where(:usage_ping_enabled, :requires_usage_stats_consent, :expected_enabled_and_consented) do # Usage ping enabled true | false | true true | true | false @@ -23,8 +23,8 @@ RSpec.describe ServicePing::ServicePingSettings do stub_config_setting(usage_ping_enabled: usage_ping_enabled) end - it 'has the correct product_intelligence_enabled?' do - expect(described_class.product_intelligence_enabled?).to eq(expected_product_intelligence_enabled) + it 'has the correct enabled_and_consented?' do + expect(described_class.enabled_and_consented?).to eq(expected_enabled_and_consented) end end end diff --git a/spec/services/service_ping/submit_service_ping_service_spec.rb b/spec/services/service_ping/submit_service_ping_service_spec.rb index 2248febda5c..ce0fa6248a1 100644 --- a/spec/services/service_ping/submit_service_ping_service_spec.rb +++ b/spec/services/service_ping/submit_service_ping_service_spec.rb @@ -104,20 +104,20 @@ RSpec.describe ServicePing::SubmitService, feature_category: :service_ping do it_behaves_like 'does not run' end - context 'when product_intelligence_enabled is false' do + context 'when enabled_and_consented is false' do before do - allow(ServicePing::ServicePingSettings).to receive(:product_intelligence_enabled?).and_return(false) + allow(ServicePing::ServicePingSettings).to receive(:enabled_and_consented?).and_return(false) end it_behaves_like 'does not run' end - context 'when product_intelligence_enabled is true' do + context 'when enabled_and_consented is true' do before do stub_usage_data_connections stub_database_flavor_check - allow(ServicePing::ServicePingSettings).to receive(:product_intelligence_enabled?).and_return(true) + allow(ServicePing::ServicePingSettings).to receive(:enabled_and_consented?).and_return(true) end it 'submits a service ping payload without errors', :aggregate_failures do -- cgit v1.2.3