diff options
94 files changed, 886 insertions, 499 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index e81b4cb920b..b61336e57c1 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1027,8 +1027,7 @@ .caching:rules:cache-assets-as-if-foss: rules: - - <<: *if-jh - when: never + - !reference [".strict-ee-only-rules", rules] - !reference [".caching:rules:cache-assets", "rules"] .caching:rules:packages-cleanup: @@ -1195,8 +1194,7 @@ rules: - <<: *if-not-canonical-namespace when: never - - <<: *if-not-ee - when: never + - !reference [".strict-ee-only-rules", rules] - !reference [.frontend:rules:compile-production-assets, rules] .frontend:rules:compile-test-assets: @@ -1853,8 +1851,7 @@ .rails:rules:single-db-as-if-foss: rules: - - <<: *if-jh - when: never + - !reference [".strict-ee-only-rules", rules] - !reference [".rails:rules:single-db", "rules"] .rails:rules:db:check-migrations-single-db: @@ -1880,8 +1877,7 @@ .rails:rules:single-db-ci-connection-as-if-foss: rules: - - <<: *if-jh - when: never + - !reference [".strict-ee-only-rules", rules] - !reference [".rails:rules:single-db-ci-connection", "rules"] .rails:rules:db:check-migrations-single-db-ci-connection: diff --git a/.rubocop.yml b/.rubocop.yml index 8ce199fd201..f42d7c7b076 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -523,6 +523,8 @@ Naming/RescuedExceptionsVariableName: RSpec/AvoidTestProf: Include: + - 'spec/tasks/**/*.rb' + - 'ee/spec/tasks/**/*.rb' - 'spec/migrations/**/*.rb' - 'ee/spec/migrations/**/*.rb' - 'spec/lib/gitlab/background_migration/**/*.rb' @@ -577,6 +579,8 @@ RSpec/BeforeAll: - 'ee/spec/**/*.rb' # Conflict with RSpec/AvoidTestProf Exclude: + - 'spec/tasks/**/*.rb' + - 'ee/spec/tasks/**/*.rb' - 'spec/migrations/**/*.rb' - 'ee/spec/migrations/**/*.rb' - 'spec/lib/gitlab/background_migration/**/*.rb' diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml index 1aedbdb1704..c123e7ebcfa 100644 --- a/.rubocop_todo/style/percent_literal_delimiters.yml +++ b/.rubocop_todo/style/percent_literal_delimiters.yml @@ -2,73 +2,6 @@ # Cop supports --autocorrect. Style/PercentLiteralDelimiters: Exclude: - - 'config/application.rb' - - 'config/boot.rb' - - 'config/environments/production.rb' - - 'config/initializers/1_settings.rb' - - 'config/initializers/content_security_policy.rb' - - 'config/initializers/doorkeeper.rb' - - 'config/initializers/enumerator_next_patch.rb' - - 'config/initializers/fog_core_patch.rb' - - 'config/initializers/forbid_sidekiq_in_transactions.rb' - - 'config/initializers/health_check.rb' - - 'config/initializers/invisible_captcha.rb' - - 'config/initializers/lograge.rb' - - 'config/initializers/rspec_profiling.rb' - - 'config/initializers_before_autoloader/000_inflections.rb' - - 'config/object_store_settings.rb' - - 'config/spring.rb' - - 'ee/app/controllers/ee/admin/application_settings_controller.rb' - - 'ee/app/controllers/ee/projects/service_desk_controller.rb' - - 'ee/app/controllers/ee/repositories/git_http_client_controller.rb' - - 'ee/app/controllers/groups/protected_environments_controller.rb' - - 'ee/app/controllers/projects/integrations/jira/issues_controller.rb' - - 'ee/app/controllers/projects/protected_environments_controller.rb' - - 'ee/app/finders/iterations_finder.rb' - - 'ee/app/graphql/types/incident_management/oncall_rotation_date_input_type.rb' - - 'ee/app/helpers/credentials_inventory_helper.rb' - - 'ee/app/helpers/ee/auth_helper.rb' - - 'ee/app/helpers/ee/dashboard_helper.rb' - - 'ee/app/helpers/ee/integrations_helper.rb' - - 'ee/app/helpers/ee/issues_helper.rb' - - 'ee/app/helpers/ee/labels_helper.rb' - - 'ee/app/helpers/ee/nav_helper.rb' - - 'ee/app/mailers/previews/ci_minutes_usage_mailer_preview.rb' - - 'ee/app/mailers/previews/emails/namespace_storage_usage_mailer_preview.rb' - - 'ee/app/mailers/previews/license_mailer_preview.rb' - - 'ee/app/models/app_sec/fuzzing/api/scan_profile.rb' - - 'ee/app/models/app_sec/fuzzing/coverage/corpus.rb' - - 'ee/app/models/concerns/ee/issue_available_features.rb' - - 'ee/app/models/ee/audit_event.rb' - - 'ee/app/models/ee/description_version.rb' - - 'ee/app/models/ee/groups/feature_setting.rb' - - 'ee/app/models/ee/issue.rb' - - 'ee/app/models/ee/project_feature.rb' - - 'ee/app/models/ee/resource_label_event.rb' - - 'ee/app/models/ee/resource_state_event.rb' - - 'ee/app/models/ee/user.rb' - - 'ee/app/models/ee/vulnerability.rb' - - 'ee/app/models/geo/project_registry.rb' - - 'ee/app/models/geo/secondary_usage_data.rb' - - 'ee/app/models/geo_node_status.rb' - - 'ee/app/models/incident_management/issuable_resource_link.rb' - - 'ee/app/models/integrations/github.rb' - - 'ee/app/models/merge_requests/status_check_response.rb' - - 'ee/app/models/saml_provider.rb' - - 'ee/app/models/security/orchestration_policy_configuration.rb' - - 'ee/app/models/software_license_policy.rb' - - 'ee/app/models/storage_shard.rb' - - 'ee/app/services/approval_rules/create_service.rb' - - 'ee/app/services/boards/epic_boards/update_service.rb' - - 'ee/app/services/ee/boards/update_service.rb' - - 'ee/app/services/ee/search/group_service.rb' - - 'ee/app/services/ee/search/project_service.rb' - - 'ee/app/services/epics/tree_reorder_service.rb' - - 'ee/app/services/iterations/update_service.rb' - - 'ee/app/services/jira/jql_builder_service.rb' - - 'ee/app/services/security/configuration/save_auto_fix_service.rb' - - 'ee/app/services/security/dependency_list_service.rb' - - 'ee/app/services/security/ingestion/tasks/update_vulnerability_uuids.rb' - 'ee/lib/api/status_checks.rb' - 'ee/lib/api/visual_review_discussions.rb' - 'ee/lib/ee/api/helpers/members_helpers.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 494619df56b..3eedc2dac46 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -2823a2218dc99fc414cb059271d49e26838537e8 +f1d2afbee25a73855d931ad2d406e04e2062dc96 diff --git a/app/assets/javascripts/commons/gitlab_ui.js b/app/assets/javascripts/commons/gitlab_ui.js new file mode 100644 index 00000000000..4a9f79460da --- /dev/null +++ b/app/assets/javascripts/commons/gitlab_ui.js @@ -0,0 +1,10 @@ +import applyGitLabUIConfig from '@gitlab/ui/dist/config'; +import { __ } from '~/locale'; + +applyGitLabUIConfig({ + translations: { + 'GlSearchBoxByType.input.placeholder': __('Search'), + 'GlSearchBoxByType.clearButtonTitle': __('Clear'), + 'ClearIconButton.title': __('Clear'), + }, +}); diff --git a/app/assets/javascripts/commons/index.js b/app/assets/javascripts/commons/index.js index 77c85d85e27..d2a5ef83faf 100644 --- a/app/assets/javascripts/commons/index.js +++ b/app/assets/javascripts/commons/index.js @@ -1,6 +1,7 @@ import './polyfills'; import './bootstrap'; import './vue'; +import './gitlab_ui'; import '../lib/utils/axios_utils'; import { openUserCountsBroadcast } from './nav/user_merge_requests'; diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index b68c7472bd5..5bfdd174694 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -8,9 +8,7 @@ import './commons'; import './behaviors'; // lib/utils -import applyGitLabUIConfig from '@gitlab/ui/dist/config'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; -import { __ } from '~/locale'; import { initRails } from '~/lib/utils/rails_ujs'; import * as popovers from '~/popovers'; import * as tooltips from '~/tooltips'; @@ -45,14 +43,6 @@ import 'jh_else_ce/main_jh'; logHelloDeferred(); -applyGitLabUIConfig({ - translations: { - 'GlSearchBoxByType.input.placeholder': __('Search'), - 'GlSearchBoxByType.clearButtonTitle': __('Clear'), - 'ClearIconButton.title': __('Clear'), - }, -}); - // expose jQuery as global (TODO: remove these) window.jQuery = jQuery; window.$ = jQuery; diff --git a/app/assets/javascripts/super_sidebar/components/brand_logo.vue b/app/assets/javascripts/super_sidebar/components/brand_logo.vue index 2e5499b6bbf..b346d3d43e8 100644 --- a/app/assets/javascripts/super_sidebar/components/brand_logo.vue +++ b/app/assets/javascripts/super_sidebar/components/brand_logo.vue @@ -26,7 +26,7 @@ export default { <template> <a - v-gl-tooltip:super-sidebar.hover.noninteractive.bottom.ds500="$options.i18n.homepage" + v-gl-tooltip:super-sidebar.hover.bottom.ds500="$options.i18n.homepage" class="brand-logo" :href="rootPath" data-track-action="click_link" diff --git a/app/assets/javascripts/super_sidebar/components/create_menu.vue b/app/assets/javascripts/super_sidebar/components/create_menu.vue index 97d11e74482..2347e74fdee 100644 --- a/app/assets/javascripts/super_sidebar/components/create_menu.vue +++ b/app/assets/javascripts/super_sidebar/components/create_menu.vue @@ -62,9 +62,7 @@ export default { <template> <gl-disclosure-dropdown - v-gl-tooltip:super-sidebar.hover.noninteractive.ds500.bottom=" - dropdownOpen ? '' : $options.i18n.createNew - " + v-gl-tooltip:super-sidebar.hover.ds500.bottom="dropdownOpen ? '' : $options.i18n.createNew" category="tertiary" icon="plus" no-caret diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue index 75083fcebef..93e004f0328 100644 --- a/app/assets/javascripts/super_sidebar/components/nav_item.vue +++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue @@ -216,7 +216,7 @@ export default { </gl-badge> <gl-button v-if="isPinnable && !isPinned" - v-gl-tooltip.noninteractive.ds500.right.viewport="$options.i18n.pinItem" + v-gl-tooltip.ds500.right.viewport="$options.i18n.pinItem" size="small" category="tertiary" icon="thumbtack" @@ -228,7 +228,7 @@ export default { /> <gl-button v-else-if="isPinnable && isPinned" - v-gl-tooltip.noninteractive.ds500.right.viewport="$options.i18n.unpinItem" + v-gl-tooltip.ds500.right.viewport="$options.i18n.unpinItem" size="small" category="tertiary" :aria-label="$options.i18n.unpinItem" diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue index f3f7dd587db..3ad59000ad3 100644 --- a/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar_toggle.vue @@ -73,7 +73,7 @@ export default { <template> <gl-button - v-gl-tooltip.hover.noninteractive.ds500="tooltip" + v-gl-tooltip.hover.ds500="tooltip" aria-controls="super-sidebar" :aria-expanded="ariaExpanded" :aria-label="$options.i18n.primaryNavigationSidebar" diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue index 810b1d02046..5d94e71c5ab 100644 --- a/app/assets/javascripts/super_sidebar/components/user_bar.vue +++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue @@ -139,7 +139,7 @@ export default { <gl-button v-if="isImpersonating" - v-gl-tooltip.noninteractive.ds500.bottom + v-gl-tooltip.ds500.bottom :href="sidebarData.stop_impersonation_path" :title="$options.i18n.stopImpersonating" :aria-label="$options.i18n.stopImpersonating" @@ -154,7 +154,7 @@ export default { class="gl-display-flex gl-justify-content-space-between gl-gap-2" > <counter - v-gl-tooltip:super-sidebar.hover.noninteractive.ds500.bottom="$options.i18n.issues" + v-gl-tooltip:super-sidebar.hover.ds500.bottom="$options.i18n.issues" class="gl-flex-basis-third dashboard-shortcuts-issues" icon="issues" :count="userCounts.assigned_issues" @@ -172,7 +172,7 @@ export default { @hidden="mrMenuShown = false" > <counter - v-gl-tooltip:super-sidebar.hover.noninteractive.ds500.bottom=" + v-gl-tooltip:super-sidebar.hover.ds500.bottom=" mrMenuShown ? '' : $options.i18n.mergeRequests " class="gl-w-full" @@ -186,7 +186,7 @@ export default { /> </merge-request-menu> <counter - v-gl-tooltip:super-sidebar.hover.noninteractive.ds500.bottom="$options.i18n.todoList" + v-gl-tooltip:super-sidebar.hover.ds500.bottom="$options.i18n.todoList" class="gl-flex-basis-third shortcuts-todos js-todos-count" icon="todo-done" :count="userCounts.todos" @@ -200,7 +200,7 @@ export default { </div> <button id="super-sidebar-search" - v-gl-tooltip.bottom.hover.noninteractive.ds500.html="searchTooltip" + v-gl-tooltip.bottom.hover.ds500.html="searchTooltip" v-gl-modal="$options.SEARCH_MODAL_ID" class="counter gl-display-block gl-py-3 gl-bg-gray-10 gl-rounded-base gl-text-gray-900 gl-border-none gl-inset-border-1-gray-a-08 gl-line-height-1 gl-focus--focus gl-w-full" data-testid="super-sidebar-search-button" diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index 6401b1070c0..a10de3836ba 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -8,6 +8,8 @@ module Registrations include ::Gitlab::Utils::StrongMemoize layout 'minimal' + # TODO: Once this is an ee + SaaS only feature, we can remove this. + # To be completed in https://gitlab.com/gitlab-org/gitlab/-/issues/411858 skip_before_action :check_two_factor_requirement helper_method :welcome_update_params diff --git a/app/models/ci/build_need.rb b/app/models/ci/build_need.rb index 8eb8a436289..00241908644 100644 --- a/app/models/ci/build_need.rb +++ b/app/models/ci/build_need.rb @@ -10,7 +10,6 @@ module Ci MAX_JOB_NAME_LENGTH = 128 columns_changing_default :partition_id - ignore_column :id_convert_to_bigint, remove_with: '16.4', remove_after: '2023-09-22' belongs_to :build, class_name: "Ci::Processable", foreign_key: :build_id, inverse_of: :needs diff --git a/app/presenters/event_presenter.rb b/app/presenters/event_presenter.rb index a098db7fbbc..8f7b2d5868e 100644 --- a/app/presenters/event_presenter.rb +++ b/app/presenters/event_presenter.rb @@ -54,4 +54,29 @@ class EventPresenter < Gitlab::View::Presenter::Delegated target.noteable_type.titleize end.downcase end + + def push_activity_description + return unless push_action? + + if batch_push? + "#{action_name} #{ref_count} #{ref_type.pluralize(ref_count)}" + else + "#{action_name} #{ref_type}" + end + end + + def batch_push? + push_action? && ref_count.to_i > 0 + end + + def linked_to_reference? + return false unless push_action? + return false if event.project.nil? + + if tag? + project.repository.tag_exists?(ref_name) + else + project.repository.branch_exists?(ref_name) + end + end end diff --git a/app/services/merge_requests/create_ref_service.rb b/app/services/merge_requests/create_ref_service.rb index a6ccd38877a..eae6845335a 100644 --- a/app/services/merge_requests/create_ref_service.rb +++ b/app/services/merge_requests/create_ref_service.rb @@ -119,12 +119,7 @@ module MergeRequests end def update_merge_request!(merge_request, result) - merge_request.merge_params['train_ref'] = - result.slice(:commit_sha, :merge_commit_sha, :squash_commit_sha).stringify_keys - merge_request.save! - rescue StandardError => e - Gitlab::ErrorTracking.track_exception(e) - raise CreateRefError, "Failed to update merge params" + # overridden in EE end def safe_gitaly_operation diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 05761b8f571..29aba3c8679 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -79,7 +79,11 @@ module MergeRequests log_info("Git merge finished on JID #{merge_jid} commit #{commit_sha}") - new_merge_request_attributes = merge_result.slice(:merge_commit_sha, :squash_commit_sha) + new_merge_request_attributes = { + merged_commit_sha: commit_sha, + merge_commit_sha: merge_result[:merge_commit_sha], + squash_commit_sha: merge_result[:squash_commit_sha] + }.compact merge_request.update!(new_merge_request_attributes) if new_merge_request_attributes.present? commit_sha diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index a230b123ea3..1af26377b71 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -187,7 +187,7 @@ module Notes namespace: project&.namespace, user: user, label: metric_key_path, - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: metric_key_path).to_context] + context: [Gitlab::Usage::MetricDefinition.context_for(metric_key_path).to_context] ) end diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index 4a6b7fcfa84..0ad969116e0 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -6,13 +6,11 @@ .event-title.d-flex.flex-wrap = inline_event_icon(event) - - many_refs = event.ref_count.to_i > 1 - %span.event-type.d-inline-block.gl-mr-2.pushed= many_refs ? "#{event.action_name} #{event.ref_count} #{event.ref_type.pluralize}" : "#{event.action_name} #{event.ref_type}" - - unless many_refs + %span.event-type.d-inline-block.gl-mr-2.pushed= event.push_activity_description + - unless event.batch_push? %span.gl-mr-2.text-truncate - commits_link = project_commits_path(project, event.ref_name) - - should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name) - = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name' + = link_to_if event.linked_to_reference?, event.ref_name, commits_link, class: 'ref-name' = render "events/event_scope", event: event diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 4971dc3775f..5345714a010 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -164,7 +164,7 @@ class PostReceive user: user, property: 'source_code_pushes', label: metric_path, - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: metric_path).to_context] + context: [Gitlab::Usage::MetricDefinition.context_for(metric_path).to_context] ) end end diff --git a/config/application.rb b/config/application.rb index b1b88440f6e..552a68f6046 100644 --- a/config/application.rb +++ b/config/application.rb @@ -213,7 +213,7 @@ module Gitlab /^title$/, /^hook$/ ] - config.filter_parameters += %i( + config.filter_parameters += %i[ certificate encrypted_key import_url @@ -230,7 +230,7 @@ module Gitlab sharedSecret redirect question - ) + ] # This config option can be removed after Rails 7.1 by https://gitlab.com/gitlab-org/gitlab/-/issues/416270 config.active_support.use_rfc4122_namespaced_uuids = true @@ -458,30 +458,30 @@ module Gitlab allow do origins { |source, env| source == Gitlab::CurrentSettings.jira_connect_proxy_url } - resource '/-/jira_connect/oauth_application_id', headers: :any, credentials: false, methods: %i(get options) + resource '/-/jira_connect/oauth_application_id', headers: :any, credentials: false, methods: %i[get options] end allow do origins { |source, env| source == Gitlab::CurrentSettings.jira_connect_proxy_url } - resource '/-/jira_connect/subscriptions.json', headers: :any, credentials: false, methods: %i(get options) + resource '/-/jira_connect/subscriptions.json', headers: :any, credentials: false, methods: %i[get options] end allow do origins { |source, env| source == Gitlab::CurrentSettings.jira_connect_proxy_url } - resource '/-/jira_connect/subscriptions/*', headers: :any, credentials: false, methods: %i(delete options) + resource '/-/jira_connect/subscriptions/*', headers: :any, credentials: false, methods: %i[delete options] end # Cross-origin requests must be enabled for the Authorization code with PKCE OAuth flow when used from a browser. - %w(/oauth/token /oauth/revoke).each do |oauth_path| + %w[/oauth/token /oauth/revoke].each do |oauth_path| allow do origins '*' resource oauth_path, # These headers are added as defaults to axios. # See: https://gitlab.com/gitlab-org/gitlab/-/blob/dd1e70d3676891025534dc4a1e89ca9383178fe7/app/assets/javascripts/lib/utils/axios_utils.js#L8) # It's added to declare that this is a XHR request and add the CSRF token without which Rails may reject the request from the frontend. - headers: %w(Authorization X-CSRF-Token X-Requested-With), + headers: %w[Authorization X-CSRF-Token X-Requested-With], credentials: false, - methods: %i(post options) + methods: %i[post options] end end @@ -490,17 +490,17 @@ module Gitlab allow do origins '*' resource '/oauth/userinfo', - headers: %w(Authorization), + headers: %w[Authorization], credentials: false, - methods: %i(get head post options) + methods: %i[get head post options] end - %w(/oauth/discovery/keys /.well-known/openid-configuration /.well-known/webfinger).each do |openid_path| + %w[/oauth/discovery/keys /.well-known/openid-configuration /.well-known/webfinger].each do |openid_path| allow do origins '*' resource openid_path, credentials: false, - methods: %i(get head) + methods: %i[get head] end end @@ -510,7 +510,7 @@ module Gitlab origins 'https://*.web-ide.gitlab-static.net' resource '/assets/webpack/*', credentials: false, - methods: %i(get head) + methods: %i[get head] end end diff --git a/config/boot.rb b/config/boot.rb index ec9470bc506..1b3f2935e3f 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -3,4 +3,4 @@ require_relative 'bundler_setup' enable_bootsnap_default_value = ENV['RAILS_ENV'] != 'production' ? '1' : '0' -require 'bootsnap/setup' if %w(1 yes true).include?(ENV.fetch('ENABLE_BOOTSNAP', enable_bootsnap_default_value)) +require 'bootsnap/setup' if %w[1 yes true].include?(ENV.fetch('ENABLE_BOOTSNAP', enable_bootsnap_default_value)) diff --git a/config/environments/production.rb b/config/environments/production.rb index 8372331024f..931677b4ad7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -43,7 +43,7 @@ Rails.application.configure do # Suppress 'Rendered template ...' messages in the log # source: http://stackoverflow.com/a/16369363 - %w{render_template render_partial render_collection}.each do |event| + %w[render_template render_partial render_collection].each do |event| ActiveSupport::Notifications.unsubscribe "#{event}.action_view" end diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 5d4e9a90018..905202418fb 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -121,7 +121,7 @@ Gitlab.ee do Settings.omniauth.providers.delete_if { |p| p.name == 'kerberos' } kerberos_spnego['name'] = 'kerberos' - omniauth_keys = %w(allow_single_sign_on auto_link_user external_providers sync_profile_from_provider allow_bypass_two_factor) + omniauth_keys = %w[allow_single_sign_on auto_link_user external_providers sync_profile_from_provider allow_bypass_two_factor] omniauth_keys.each do |key| next unless Settings.omniauth[key].is_a?(Array) @@ -1090,7 +1090,7 @@ Settings.extra['maximum_text_highlight_size_kilobytes'] = Settings.extra.fetch(' Settings['rack_attack'] ||= {} Settings.rack_attack['git_basic_auth'] ||= {} Settings.rack_attack.git_basic_auth['enabled'] = false if Settings.rack_attack.git_basic_auth['enabled'].nil? -Settings.rack_attack.git_basic_auth['ip_whitelist'] ||= %w{127.0.0.1} +Settings.rack_attack.git_basic_auth['ip_whitelist'] ||= %w[127.0.0.1] Settings.rack_attack.git_basic_auth['maxretry'] ||= 10 Settings.rack_attack.git_basic_auth['findtime'] ||= 1.minute Settings.rack_attack.git_basic_auth['bantime'] ||= 1.hour diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index f7c3f4e98b5..4ab94797f26 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -15,5 +15,5 @@ if csp_settings['enabled'] Rails.application.config.content_security_policy_report_only = csp_settings['report_only'] Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) } - Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + Rails.application.config.content_security_policy_nonce_directives = %w[script-src] end diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 73608a367d8..9c553b018c5 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -101,7 +101,7 @@ Doorkeeper.configure do # "password" => Resource Owner Password Credentials Grant Flow # "client_credentials" => Client Credentials Grant Flow # - grant_flows %w(authorization_code password client_credentials) + grant_flows %w[authorization_code password client_credentials] # Under some circumstances you might want to have applications auto-approved, # so that the user skips the authorization step. diff --git a/config/initializers/enumerator_next_patch.rb b/config/initializers/enumerator_next_patch.rb index e1fc04731ae..3771864fb91 100644 --- a/config/initializers/enumerator_next_patch.rb +++ b/config/initializers/enumerator_next_patch.rb @@ -4,7 +4,7 @@ # when an error is raised from within a Fiber. # https://bugs.ruby-lang.org/issues/16829 module EnumeratorNextPatch - %w(next next_values peek peek_values).each do |name| + %w[next next_values peek peek_values].each do |name| define_method(name) do |*args| gitlab_patch_backtrace_marker { super(*args) } rescue Exception => err # rubocop: disable Lint/RescueException @@ -27,7 +27,7 @@ module EnumeratorNextPatch # #gitlab_patch_backtrace_marker calls a block, which in turn calls #next.) If it's generated # by the Fiber that #next invokes, then it won't contain this marker. def has_gitlab_patch_backtrace_marker?(backtrace) - match = %r(^(.*):[0-9]+:in `gitlab_patch_backtrace_marker'$).match(backtrace[2]) + match = %r{^(.*):[0-9]+:in `gitlab_patch_backtrace_marker'$}.match(backtrace[2]) !!match && match[1] == __FILE__ end diff --git a/config/initializers/fog_core_patch.rb b/config/initializers/fog_core_patch.rb index f7d81f26be5..d0868116a7a 100644 --- a/config/initializers/fog_core_patch.rb +++ b/config/initializers/fog_core_patch.rb @@ -31,7 +31,7 @@ module Fog module ServicesMixin # Gems that have not yet updated with the new fog-core namespace - LEGACY_FOG_PROVIDERS = %w(google aliyun).freeze + LEGACY_FOG_PROVIDERS = %w[google aliyun].freeze # rubocop:disable Gitlab/ConstGetInheritFalse def service_provider_constant(service_name, provider_name) diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb index c96524b824d..6dd12c28515 100644 --- a/config/initializers/forbid_sidekiq_in_transactions.rb +++ b/config/initializers/forbid_sidekiq_in_transactions.rb @@ -36,7 +36,7 @@ module Sidekiq module ClassMethods module NoEnqueueingFromTransactions - %i(perform_async perform_at perform_in).each do |name| + %i[perform_async perform_at perform_in].each do |name| define_method(name) do |*args| if Sidekiq::Worker.raise_exception_for_being_inside_a_transaction? begin @@ -65,7 +65,7 @@ end module ActiveJob module QueueAdapters module NoEnqueueingFromTransactions - %i(enqueue enqueue_at).each do |name| + %i[enqueue enqueue_at].each do |name| define_method(name) do |*args| if Sidekiq::Worker.raise_exception_for_being_inside_a_transaction? begin diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb index 0b35aaf115b..a35c757c6fa 100644 --- a/config/initializers/health_check.rb +++ b/config/initializers/health_check.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true HealthCheck.setup do |config| - config.standard_checks = %w(database migrations cache) - config.full_checks = %w(database migrations cache) + config.standard_checks = %w[database migrations cache] + config.full_checks = %w[database migrations cache] Gitlab.ee do config.add_custom_check('geo') do diff --git a/config/initializers/invisible_captcha.rb b/config/initializers/invisible_captcha.rb index 5177c730596..499217a6d56 100644 --- a/config/initializers/invisible_captcha.rb +++ b/config/initializers/invisible_captcha.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true InvisibleCaptcha.setup do |config| - config.honeypots = %w(firstname lastname) + config.honeypots = %w[firstname lastname] config.timestamp_enabled = true config.timestamp_threshold = 4 end diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb index 5ea3b553713..6ed3fff7f46 100644 --- a/config/initializers/lograge.rb +++ b/config/initializers/lograge.rb @@ -23,7 +23,7 @@ unless Gitlab::Runtime.sidekiq? # Remove empty hashes to prevent type mismatches # These are set to empty hashes in Lograge's ActionCable subscriber # https://github.com/roidrage/lograge/blob/v0.11.2/lib/lograge/log_subscribers/action_cable.rb#L14-L16 - %i(method path format).each do |key| + %i[method path format].each do |key| data[key] = nil if data[key] == {} end diff --git a/config/initializers/rspec_profiling.rb b/config/initializers/rspec_profiling.rb index 7cc2d6afb0f..b0b7ea85cae 100644 --- a/config/initializers/rspec_profiling.rb +++ b/config/initializers/rspec_profiling.rb @@ -5,8 +5,8 @@ return unless Rails.env.test? module RspecProfilingExt module Collectors class CSVWithTimestamps < ::RspecProfiling::Collectors::CSV - TIMESTAMP_FIELDS = %w(created_at updated_at).freeze - METADATA_FIELDS = %w(feature_category).freeze + TIMESTAMP_FIELDS = %w[created_at updated_at].freeze + METADATA_FIELDS = %w[feature_category].freeze HEADERS = (::RspecProfiling::Collectors::CSV::HEADERS + TIMESTAMP_FIELDS + METADATA_FIELDS).freeze def insert(attributes) diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb index e4f1c48b0b4..6f73dbb4d8a 100644 --- a/config/initializers_before_autoloader/000_inflections.rb +++ b/config/initializers_before_autoloader/000_inflections.rb @@ -12,7 +12,7 @@ # end # ActiveSupport::Inflector.inflections do |inflect| - inflect.uncountable %w( + inflect.uncountable %w[ custom_emoji award_emoji ci_secure_file_registry @@ -40,7 +40,7 @@ ActiveSupport::Inflector.inflections do |inflect| terraform_state_version_registry vulnerabilities_feedback vulnerability_feedback - ) + ] inflect.acronym 'CDN' inflect.acronym 'EE' inflect.acronym 'JH' diff --git a/config/metrics/counts_28d/20220428154012_live_preview.yml b/config/metrics/counts_28d/20220428154012_live_preview.yml index 0a5e64bf472..91ad9718aad 100644 --- a/config/metrics/counts_28d/20220428154012_live_preview.yml +++ b/config/metrics/counts_28d/20220428154012_live_preview.yml @@ -23,3 +23,5 @@ tier: - ultimate performance_indicator_type: [] milestone: "15.0" +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131356 +milestone_removed: '16.4' diff --git a/config/object_store_settings.rb b/config/object_store_settings.rb index 4e8e950c797..283cd952c04 100644 --- a/config/object_store_settings.rb +++ b/config/object_store_settings.rb @@ -2,19 +2,19 @@ # Set default values for object_store settings class ObjectStoreSettings - SUPPORTED_TYPES = %w(artifacts external_diffs lfs uploads packages dependency_proxy terraform_state pages).freeze - ALLOWED_OBJECT_STORE_OVERRIDES = %w(bucket enabled proxy_download cdn).freeze + SUPPORTED_TYPES = %w[artifacts external_diffs lfs uploads packages dependency_proxy terraform_state pages].freeze + ALLOWED_OBJECT_STORE_OVERRIDES = %w[bucket enabled proxy_download cdn].freeze # To ensure the one Workhorse credential matches the Rails config, we # enforce consolidated settings on those accelerated # endpoints. Technically dependency_proxy and terraform_state fall # into this category, but they will likely be handled by Workhorse in # the future. - WORKHORSE_ACCELERATED_TYPES = SUPPORTED_TYPES - %w(pages) + WORKHORSE_ACCELERATED_TYPES = SUPPORTED_TYPES - %w[pages] # pages may be enabled but use legacy disk storage # we don't need to raise an error in that case - ALLOWED_INCOMPLETE_TYPES = %w(pages).freeze + ALLOWED_INCOMPLETE_TYPES = %w[pages].freeze attr_accessor :settings diff --git a/config/spring.rb b/config/spring.rb index f06a707111c..8fb1ae1669d 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -%w( +%w[ .ruby-version .rbenv-vars tmp/restart.txt tmp/caching-dev.txt -).each { |path| Spring.watch(path) } +].each { |path| Spring.watch(path) } Spring.after_fork do if ENV['DEBUGGER_STORED_RUBYLIB'] diff --git a/doc/ci/components/catalog.md b/doc/ci/components/catalog.md index 3a3f63365bb..12e795073b7 100644 --- a/doc/ci/components/catalog.md +++ b/doc/ci/components/catalog.md @@ -6,17 +6,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w # CI/CD Catalog **(PREMIUM ALL EXPERIMENT)** +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407249) in GitLab 16.1. + The CI/CD Catalog is a list of [components repositories](index.md#components-repository), each containing resources that you can add to your CI/CD pipelines. -## Mark the project as a catalog resource - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407249) in GitLab 16.1. +## Mark a components repository as a catalog resource -After components are added to a components repository, they can immediately be [used](index.md#use-a-component-in-a-cicd-configuration) to build pipelines in other projects. +After components are added to a components repository, they can immediately be [used](index.md#use-a-component-in-a-cicd-configuration) +to build pipelines in other projects. -However, this repository is not discoverable. You must mark this project as a catalog resource to allow it to be visible in the CI Catalog -so other users can discover it. +However, this repository is not discoverable. You must mark this project as a catalog resource +to allow it to be visible in the CI/CD Catalog so other users can discover it. To mark a project as a catalog resource: @@ -25,19 +26,8 @@ To mark a project as a catalog resource: 1. Expand **Visibility, project features, permissions**. 1. Scroll down to **CI/CD Catalog resource** and select the toggle to mark the project as a catalog resource. -On the left sidebar, select **Search or go to** and find your project. +Ensure the project has a clear [description](../../user/project/settings/index.md#edit-project-name-and-description), +as the project description is displayed in the component list in the catalog. NOTE: This action is not reversible. - -## Convert a CI template to component - -Any existing CI template, that you share with other projects via `include:` syntax, can be converted to a CI component. - -1. Decide whether you want the component to be part of an existing [components repository](index.md#components-repository), - if you want to logically group components together. Create and setup a [components repository](index.md#components-repository) otherwise. -1. Create a YAML file in the components repository according to the expected [directory structure](index.md#directory-structure). -1. Copy the content of the template YAML file into the new component YAML file. -1. Refactor the component YAML to follow the [best practices](index.md#best-practices) for components. -1. Leverage the `.gitlab-ci.yml` in the components repository to [test changes to the component](index.md#test-a-component). -1. Tag and [release the component](index.md#release-a-component). diff --git a/doc/ci/components/index.md b/doc/ci/components/index.md index d4ed98893af..377a9a2147d 100644 --- a/doc/ci/components/index.md +++ b/doc/ci/components/index.md @@ -15,15 +15,19 @@ to track future work. Tell us about your use case by leaving comments in the epi ## Components Repository -A components repository is a GitLab project with a repository that hosts one or more pipeline components. A pipeline component is a reusable single pipeline configuration unit. You can use them to compose an entire pipeline configuration or a small part of a larger pipeline. It can optionally take [input parameters](../yaml/includes.md#define-input-parameters-with-specinputs). +A components repository is a GitLab project with a repository that hosts one or more pipeline components. +A pipeline component is a reusable single pipeline configuration unit. You can use them to compose +an entire pipeline configuration or a small part of a larger pipeline. -### Create a components repository +A component can optionally take [input parameters](../yaml/includes.md#define-input-parameters-with-specinputs). + +## Create a components repository To create a components repository, you must: 1. [Create a new project](../../user/project/index.md#create-a-blank-project) with a `README.md` file. - -1. Create a `template.yml` file inside the project's root directory that contains the configuration you want to provide as a component. For example: +1. Create a `template.yml` file inside the project's root directory that contains the configuration you want to provide as a component. + For example: ```yaml spec: @@ -116,8 +120,8 @@ namespace named `my-username`: └── .gitlab-ci.yml ``` - The `.gitlab-ci.yml` file is not required for a CI/CD component to work, but [testing the component](#test-a-component) - in a pipeline in the project is recommended. + The `.gitlab-ci.yml` file is not required for a CI/CD component to work, but + [testing the component](#test-the-component) in a pipeline in the project is recommended. This component is referenced with the path `gitlab.com/my-username/my-component@<version>`. @@ -154,248 +158,282 @@ Nesting of components is not possible. For example: │ └── nested_template.yml ``` -### Test a component +## Release a component + +To create a release for a CI/CD component, you can use: + +- The [`release`](../yaml/index.md#release) keyword in a CI/CD pipeline. Like in the + [component testing example](#test-the-component), you can set a component to automatically + be released after all tests pass in pipelines for new tags. +- The [UI for creating a release](../../user/project/releases/index.md#create-a-release). + +All released versions of the components are displayed in the CI/CD Catalog +page for the given resource, providing users with information about official releases. -Testing CI/CD components as part of the development workflow is strongly recommended and helps ensure consistent behavior. +Components [can be used](#use-a-component-in-a-cicd-configuration) without being released, +but only with a commit SHA or a branch name. To enable the use of tags or the `~latest` version keyword, +you must create a release. -Test changes in a CI/CD pipeline like any other project, by creating a `.gitlab-ci.yml` file in the root directory of the component repository. +## Use a component in a CI/CD configuration +You can add a component to a CI/CD configuration with the `include: component` keyword. For example: ```yaml include: - # include the component located in the current project from the current SHA - - component: gitlab.com/$CI_PROJECT_PATH@$CI_COMMIT_SHA + - component: gitlab.example.com/my-namespace/my-component@1.0 inputs: stage: build +``` -stages: [build, test, release] - -# Expect `component-job` is added. -# This is an example of testing that the included component works as expected. -# You can leverage GitLab API endpoints or 3rd party tools to inspect data generated by the component. -ensure-job-added: - stage: test - image: badouralix/curl-jq - script: - - | - route="https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs" - count=`curl --silent --header "PRIVATE-TOKEN: $API_TOKEN" $route | jq 'map(select(.name | contains("component-job"))) | length'` - if [ "$count" != "1" ]; then - exit 1 - fi +The component is identified by a unique address in the form `<fully-qualified-doman-name>/<component-path>@<specific-version>`, +where: + +- `<fully-qualified-doman-name>` matches the GitLab host. +- `<component-path>` is the component project's full path and directory where the + component YAML file is located. +- `<specific-version>` is the version of the component. In order of highest priority first, + the version can be: + - A commit SHA, for example `e3262fdd0914fa823210cdb79a8c421e2cef79d8`. + - A tag, for example: `1.0`. + - `~latest`, which is a special version that always points to the most recent released tag. + Only available if the component has been [released](#release-a-component). + - A branch name, for example `main`. + +For example, for a component repository located at `gitlab-org/dast` on `gitlab.com`, +the path: + +- `gitlab.com/gitlab-org/dast@main` targets the `template.yml` in the root directory + on the `main` branch. +- `gitlab.com/gitlab-org/dast@e3262fdd0914fa823210cdb79a8c421e2cef79d8` targets the same file + for the specified commit SHA. +- `gitlab.com/gitlab-org/dast@1.0` targets the same file for the `1.0` tag. +- `gitlab.com/gitlab-org/dast@~latest` targets the same file for the latest release. +- `gitlab.com/gitlab-org/dast/api-scan@main` targets a different file, the `template.yml` + in the `/api-scan` directory in the component repository, for the `main` branch. + +**Additional details**: -# If we are tagging a release with a specific convention ("v" + number) and all -# previous checks succeeded, we proceed with creating a release automatically. -create-release: - stage: release - image: registry.gitlab.com/gitlab-org/release-cli:latest - rules: - - if: $CI_COMMIT_TAG =~ /^v\d+/ - script: echo "Creating release $CI_COMMIT_TAG" - release: - tag_name: $CI_COMMIT_TAG - description: "Release $CI_COMMIT_TAG of components repository $CI_PROJECT_PATH" -``` +- You can only reference components in the same GitLab instance as your project. +- If a tag and branch exist with the same name, the tag takes precedence over the branch. +- If a tag is named the same as a commit SHA that exists, like `e3262fdd0914fa823210cdb79a8c421e2cef79d8`, + the commit SHA takes precedence over the tag. -After committing and pushing changes, the pipeline tests the component then releases it if the test passes. +## Best practices -### Release a component +### Avoid using global keywords -To create a release for a CI/CD component, you can use: +You should try to avoid [global keywords](../yaml/index.md#global-keywords) in a component. +Using these keywords in a component affects all jobs in a pipeline, including jobs +directly defined in the main `.gitlab-ci.yml` or in other included components. -- The [`release`](../yaml/index.md#release) keyword in a CI/CD pipeline. -- The [UI for creating a release](../../user/project/releases/index.md#create-a-release). +As an alternative to global keywords, you should instead: -Like in the [example above](#test-a-component), after all tests pass in a pipeline running for a tag ref, we can release a new version of the components repository. +- Add the configuration directly to each job, even if it creates some duplication + in the component configuration. +- Use the [`extends`](../yaml/index.md#extends) keyword in the component. -All released versions of the components repository are displayed in the Components Catalog page for the given resource, providing users with information about official releases. +For example, using the `default` keyword is not recommended: -Components [can be used](#use-a-component-in-a-cicd-configuration) without being released, but only with a commit SHA or a branch name. To enable the use of tags or the `~latest` version keyword, you must create a release. +```yaml +# Not recommended +default: + image: ruby:3.0 -### Use a component in a CI/CD configuration +rspec-1: + script: bundle exec rspec dir1/ -A pipeline component is identified by a unique address in the form `<fully-qualified-doman-name>/<component-path>@<version>` -containing: +rspec-2: + script: bundle exec rspec dir2/ +``` -- **A fully qualified domain name (FQDN)**: The FQDN must match the GitLab host. -- **A specific version**: The version of the component can be (in order of highest priority first): - - A commit SHA, for example `gitlab.com/gitlab-org/dast@e3262fdd0914fa823210cdb79a8c421e2cef79d8`. - - A tag. for example: `gitlab.com/gitlab-org/dast@1.0`. - - `~latest`, which is a special version that always points to the most recent released tag, - for example `gitlab.com/gitlab-org/dast@~latest`. - - A branch name, for example `gitlab.com/gitlab-org/dast@main`. -- **A component path**: Contains the project's full path and the directory where the component YAML file `template.yml` is located. +Instead, you can: -For example, for a component repository located at `gitlab-org/dast` on `gitlab.com`: +- Add the configuration to each job: -- The path `gitlab.com/gitlab-org/dast` tries to load the `template.yml` from the root directory. -- The path `gitlab.com/gitlab-org/dast/api-scan` tries to load the `template.yml` from the `/api-scan` directory. + ```yaml + rspec-1: + image: ruby:3.0 + script: bundle exec rspec dir1/ -**Additional notes:** + rspec-2: + image: ruby:3.0 + script: bundle exec rspec dir2/ + ``` -- You can only reference components in the same GitLab instance as your project. -- If a tag and branch exist with the same name, the tag takes precedence over the branch. -- If a tag is named the same as a commit SHA that exists, like `e3262fdd0914fa823210cdb79a8c421e2cef79d8`, - the commit SHA takes precedence over the tag. +- Use `extends` to reuse configuration: -### Best practices + ```yaml + .rspec-image: + image: ruby:3.0 -#### Avoid using global keywords + rspec-1: + extends: + - .rspec-image + script: bundle exec rspec dir1/ -When using [global keywords](../yaml/index.md#global-keywords) all jobs in the -pipeline are affected. Using these keywords in a component affects all jobs in a -pipeline, whether they are directly defined in the main `.gitlab-ci.yml` or -in any included components. + rspec-2: + extends: + - .rspec-image + script: bundle exec rspec dir2/ + ``` -To make the composition of pipelines more deterministic, either: +### Replace hard-coded values with inputs -- Duplicate the default configuration for each job. -- Use [`extends`](../yaml/index.md#extends) feature within the component. +You should avoid hard-coding values in a CI/CD components. Hard-coded values might force +component users to need to review the component's internal details and adapt their pipeline +to work with the component. -```yaml -## -# BAD -default: - image: ruby:3.0 +A common keyword with problematic hard-coded values is `stage`. If a component job's +stage is set to a specific value, the pipeline using the component **must** define +the exact same stage. Additionally, if the component user wants to use a different stage, +they must [override](../yaml/includes.md#override-included-configuration-values) the configuration. -rspec: - script: bundle exec rspec -``` +The preferred method is to use the [`input` keyword](../yaml/includes.md#define-input-parameters-with-specinputs). +The component user can specify the exact value they need. -```yaml -## -# GOOD -rspec: - image: ruby:3.0 - script: bundle exec rspec -``` +For example: -#### Replace hard-coded values with inputs +- In the component configuration: -A typical hard-coded value found in CI templates is `stage:` value. Such hard coded values may force the user -of the component to know and adapt the pipeline to such implementation details. + ```yaml + spec: + inputs: + stage: + default: test + --- + unit-test: + stage: $[[ inputs.stage ]] + script: echo unit tests + + integration-test: + stage: $[[ inputs.stage ]] + script: echo integration tests + ``` -For example, if `stage: test` is hard-coded for a job in a component, the pipeline using the component must -define the `test` stage. Additionally, if the user of the component want to customize the stage value it has -to override the configuration: +- In the project using the component: -```yaml -## -# BAD: In order to use different stage name you need to override all the jobs -# included by the component. -include: - - component: gitlab.com/gitlab-org/ruby-test@1.0 + ```yaml + include: + - component: gitlab.com/gitlab-org/ruby-test@1.0 + inputs: + stage: verify -stages: [verify, deploy] + stages: [verify, deploy] + ``` -unit-test: - stage: verify +### Replace custom CI/CD variables with inputs -integration-test: - stage: verify -``` +When using CI/CD variables in a component, you should evaluate if the `inputs` keyword +should be used instead. Requiring a user to define custom variables to change a component's +behavior should be avoided. You should try to use `inputs` for any component customization. -```yaml -## -# BAD: In order to use the component correctly you need to define the stage -# that is hard-coded in it. -include: - - component: gitlab.com/gitlab-org/ruby-test@1.0 +Inputs are explicitly defined in the component's specs and are better validated than variables. +For example, if a required input is not passed to the component, GitLab returns a pipeline error. +By contrast, if a variable is not defined, it's value is empty and there is no error. -stages: [test, deploy] -``` +For example, use `inputs` instead of variables to let users change a scanner's output format: -To improve this we can use [input parameters](../yaml/includes.md#define-input-parameters-with-specinputs) -allowing the user of a component to inject values that can be customized: +- In the component configuration: -```yaml -## -# GOOD: We don't need to know the implementation details of a component and instead we can -# rely on the inputs. -include: - - component: gitlab.com/gitlab-org/ruby-test@1.0 + ```yaml + spec: inputs: - stage: verify + scanner-output: + default: json + --- + my-scanner: + script: my-scan --output $[[ inputs.scanner-output ]] + ``` -stages: [verify, deploy] +- In the project using the component: -## -# inside the component's template.yml file: -spec: - inputs: - stage: - default: test ---- -unit-test: - stage: $[[ inputs.stage ]] - script: echo unit tests + ```yaml + include: + - component: gitlab.example.com/my-scanner@1.0 + inputs: + scanner-output: yaml + ``` -integration-test: - stage: $[[ inputs.stage ]] - script: echo integration tests -``` +In other cases, CI/CD variables are still preferred, including: -#### Prefer inputs over variables +- Using [predefined variables](../variables/predefined_variables.md) to automatically configure + a component to match a user's project. +- Requiring tokens or other sensitive values to be stored as [masked or protected variables in project settings](../variables/index.md#define-a-cicd-variable-in-the-ui). -If variables are only used for YAML evaluation (for example `rules`) and not by the Runner -execution, it's advised to use inputs instead. -Inputs are explicitly defined in the component's contract and they are better validated -than variables. +### Use semantic versioning -For example, if a required input is not passed an error is returned as soon as the component -is being used. By contrast, if a variable is not defined, it's value is empty. +When tagging and releasing new versions of components, you should use [semantic versioning](https://semver.org). +Semantic versioning is the standard for communicating that a change is a major, minor, patch +or other kind of change. -```yaml -## -# BAD: you need to configure an environment variable for a custom value that doesn't need -# to be used on the Runner -unit-test: - image: $MY_COMPONENT_X_IMAGE - script: echo unit tests - -integration-test: - image: $MY_COMPONENT_X_IMAGE - script: echo integration tests - -## -# Usage: -include: - - component: gitlab.com/gitlab-org/ruby-test@1.0 +You should use at least the `major.minor` format, as this is widely understood, for example +`2.0` or `2.1`. -variables: - MY_COMPONENT_X_IMAGE: ruby:3.2 -``` +Other examples of semantic versioning: -```yaml -## -# GOOD: we define a customizable value and accept it as input -spec: - inputs: - image: - default: ruby:3.0 ---- -unit-test: - image: $[[ inputs.image ]] - script: echo unit tests +- `1.0.0` +- `2.1.3` +- `1.0.0-alpha` +- `3.0.0-rc1` -integration-test: - image: $[[ inputs.image ]] - script: echo integration tests +### Test the component -## -# Usage: +Testing CI/CD components as part of the development workflow is strongly recommended +and helps ensure consistent behavior. + +You can test changes in a CI/CD pipeline (like any other project) by creating a `.gitlab-ci.yml` +in the root directory. + +For example: + +```yaml include: - - component: gitlab.com/gitlab-org/ruby-test@1.0 + # include the component located in the current project from the current SHA + - component: gitlab.com/$CI_PROJECT_PATH@$CI_COMMIT_SHA inputs: - image: ruby:3.2 + stage: build + +stages: [build, test, release] + +# Expect `component-job` is added. +# This is an example of testing that the included component works as expected. +# You can leverage GitLab API endpoints or 3rd party tools to inspect data generated by the component. +ensure-job-added: + stage: test + image: badouralix/curl-jq + script: + - | + route="https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs" + count=`curl --silent --header "PRIVATE-TOKEN: $API_TOKEN" $route | jq 'map(select(.name | contains("component-job"))) | length'` + if [ "$count" != "1" ]; then + exit 1 + fi + +# If we are tagging a release with a specific convention ("v" + number) and all +# previous checks succeeded, we proceed with creating a release automatically. +create-release: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG =~ /^v\d+/ + script: echo "Creating release $CI_COMMIT_TAG" + release: + tag_name: $CI_COMMIT_TAG + description: "Release $CI_COMMIT_TAG of components repository $CI_PROJECT_PATH" ``` -#### Use semantic versioning +After committing and pushing changes, the pipeline tests the component then releases it if the test passes. -When tagging and releasing new versions of components we recommend using [semantic versioning](https://semver.org) -which is the standard for communicating bugfixes, minor and major or breaking changes. +## Convert a CI/CD template to a component -We recommend adopting at least the `MAJOR.MINOR` format. +Any existing CI/CD template that you use in projects by using the `include:` syntax +can be converted to a CI/CD component: -For example: `2.1`, `1.0.0`, `1.0.0-alpha`, `2.1.3`, `3.0.0-rc.1`. +1. Decide if you want the component to be part of an existing [components repository](index.md#components-repository) + to be grouped with other components, or create and set up a new components repository. +1. Create a YAML file in the components repository according to the expected [directory structure](index.md#directory-structure). +1. Copy the content of the original template YAML file into the new component YAML file. +1. Refactor the new component's configuration to follow the [best practices](index.md#best-practices) for components. +1. Leverage the `.gitlab-ci.yml` in the components repository to [test changes to the component](index.md#test-the-component). +1. Tag and [release the component](index.md#release-a-component). diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md index 1ccdd1b6756..d02c2f9c54e 100644 --- a/doc/ci/migration/jenkins.md +++ b/doc/ci/migration/jenkins.md @@ -321,6 +321,39 @@ my_job: - if: $CI_COMMIT_BRANCH ``` +## Secrets Management + +Privileged information, often referred to as "secrets", is sensitive information +or credentials you need in your CI/CD workflow. You might use secrets to unlock protected resources +or sensitive information in tools, applications, containers, and cloud-native environments. + +Secrets management in Jenkins is usually handled with the `Secret` type field or the +Credentials Plugin. Credentials stored in the Jenkins settings can be exposed to +jobs as environment variables by using the Credentials Binding plugin. + +For secrets management in GitLab, you can use one of the supported integrations +for an external service. These services securely store secrets outside of your GitLab project, +though you must have a subscription for the service: + +- [HashiCorp Vault](../secrets/id_token_authentication.md#automatic-id-token-authentication-with-hashicorp-vault) +- [Azure Key Vault](../secrets/azure_key_vault.md). + +GitLab also supports [OIDC authentication](../secrets/id_token_authentication.md) +for other third party services that support OIDC. + +Additionally, you can make credentials available to jobs by storing them in CI/CD variables, though secrets +stored in plain text are susceptible to accidental exposure, [the same as in Jenkins](https://www.jenkins.io/doc/developer/security/secrets/#storing-secrets). +You should always store sensitive information in [masked](../variables/index.md#mask-a-cicd-variable) +and [protected](../variables/index.md#protect-a-cicd-variable) variables, which mitigates +some of the risk. + +Also, never store secrets as variables in your `.gitlab-ci.yml` file, which is public to all +users with access to the project. Storing sensitive information in variables should +only be done in [the project, group, or instance settings](../variables/index.md#define-a-cicd-variable-in-the-ui). + +Review the [security guidelines](../variables/index.md#cicd-variable-security) to improve +the safety of your CI/CD variables. + ## Additional resources - You can use the [JenkinsFile Wrapper](https://gitlab.com/gitlab-org/jfr-container-builder/) diff --git a/doc/development/event_store.md b/doc/development/event_store.md index c54e6ae2d07..918da8fb738 100644 --- a/doc/development/event_store.md +++ b/doc/development/event_store.md @@ -300,6 +300,21 @@ executed synchronously every time the given event is published. For complex conditions it's best to subscribe to all the events and then handle the logic in the `handle_event` method of the subscriber worker. +### Delayed dispatching of events + +A subscription can specify a delay when to receive an event: + +```ruby +store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, + to: ::Ci::PipelineCreatedEvent, + delay: 1.minute +``` + +The `delay` parameter switches the dispatching of the event to use `perform_in` method +on the subscriber Sidekiq worker, instead of `perform_async`. + +This technique is useful when publishing many events and leverage the Sidekiq deduplication. + ## Testing ### Testing the publisher diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index d785cd3388d..49739d7c8e9 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -911,7 +911,8 @@ so we need to set some guidelines for their use going forward: ### Common test setup NOTE: -`before_all` does not work with the `:delete` strategy. For more information, see [issue 420379](https://gitlab.com/gitlab-org/gitlab/-/issues/420379). +`let_it_be` and `before_all` do not work with DatabaseCleaner's deletion strategy. This includes migration specs, Rake task specs, and specs that have the `:delete` RSpec metadata tag. +For more information, see [issue 420379](https://gitlab.com/gitlab-org/gitlab/-/issues/420379). In some cases, there is no need to recreate the same object for tests again for each example. For example, a project and a guest of that project @@ -1060,7 +1061,7 @@ Failing with an error along the lines of: ```shell expected { "assignee_id" => nil, "...1 +0000 } to include {"customer_relations_contacts" => [{:created_at => "2023-08-04T13:30:20Z", :first_name => "Sidney Jones3" }]} - + Diff: @@ -1,35 +1,69 @@ -"customer_relations_contacts" => [{:created_at=>"2023-08-04T13:30:20Z", :first_name=>"Sidney Jones3" }], diff --git a/doc/tutorials/scan_execution_policy/index.md b/doc/tutorials/scan_execution_policy/index.md new file mode 100644 index 00000000000..d0122908e19 --- /dev/null +++ b/doc/tutorials/scan_execution_policy/index.md @@ -0,0 +1,197 @@ +--- +stage: Govern +group: Security Policies +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Tutorial: Set up a scan execution policy **(ULTIMATE ALL)** + +This tutorial shows you how to create and apply a +[scan execution policy](../../user/application_security/policies/scan-execution-policies.md). +These policies enforce application security tools as part of the CI/CD pipeline. In this tutorial, +you create a policy to enforce secret detection in the CI/CD pipeline of two projects. + +In this tutorial, you: + +- [Create project A](#create-project-a). +- [Create the scan execution policy](#create-the-scan-execution-policy). +- [Test the scan execution policy with project A](#test-the-scan-execution-policy-with-project-a). +- [Create project B](#create-project-b). +- [Link project B to the security policy project](#link-project-b-to-the-security-policy-project). +- [Test the scan execution policy with project B](#test-the-scan-execution-policy-with-project-b). + +Prerequisite: + +- Permission to create new projects in an existing group. + +## Create project A + +In a standard workflow, you might already have an existing project. In this +tutorial, you're starting with nothing, so the first step is to create a project. + +To create project A: + +1. On the left sidebar, select **Search or go to** and find your group. +1. Select **New project**. +1. Select **Create blank project**. +1. Complete the fields. For **Project name**, enter `go-example-a`. +1. Select **Create project**. +1. Select **Add (`+`) > New file**. +1. Enter `helloworld.go` in the filename. +1. Copy and paste the following example Go code into the file. + + ```go + package main + import "fmt" + func main() { + fmt.Println("Hello world") + } + ``` + +1. Select **Commit changes**. + +The next step is to create a scan execution policy. When the first security policy is created, a +policy project is created. The policy project stores the security policies created in any projects +that are linked to it. Keeping policies separate from the projects they protect makes your security +configuration reusable and easier to maintain. + +## Create the scan execution policy + +To create the scan execution policy: + +1. On the left sidebar, select **Search or go to** and search for the `go-example-a` project. +1. Go to **Secure > Policies**. +1. Select **New policy**. +1. In the **Scan execution policy** section, select **Select policy**. +1. Complete the fields. + - **Name**: Enforce secret detection. + - **Policy status**: Enabled. + - **Actions**: Run a Secret Detection scan. + - **Conditions**: Triggers every time a pipeline runs for all branches. +1. Select **Configure with a merge request**. + + The policy project `go-example-a - Security project` is created, and a merge request is created. + +1. Optional. Review the generated policy YAML in the merge request's **Changes** tab. +1. Go to the **Overview** tab and select **Merge**. +1. On the left sidebar, select **Search or go to** and search for the `go-example-a` project. +1. Go to **Secure > Policies**. + +You now have a scan execution policy that runs a secret detection scan on every MR, for any branch. +Test the policy by creating a merge request in project A. + +## Test the scan execution policy with project A + +To test the scan execution policy: + +1. On the left sidebar, select **Search or go to** and find the project named `go-example-a`. +1. Go to **Code > Repository**. +1. Select the `helloworld.go` file. +1. Select **Edit > Edit single file**. +1. Add the following line immediately after the `fmt.Println("hello world")` line: + + ```plaintext + var GitLabFeedToken = "feed_token=eFLISqaBym4EjAefkl58" + ``` + +1. In the **Target Branch** field, enter `feature-a`. +1. Select **Commit changes**. +1. When the merge request page opens, select **Create merge request**. + + Let's check if the scan execution policy worked. Remember that we specified that secret detection + is to run every time a pipeline runs, for any branch. + +1. In the merge request just created, go the **Pipelines** tab and select the created pipeline. + + Here you can see that a secret detection job ran. Let's check if it detected the test secret. + +1. Select the secret detection job. + + Near the bottom of the job's log, the following output confirms that the example secret was detected. + + ```plaintext + [INFO] [secrets] [2023-09-04T03:46:36Z] ▶ 3:46AM INF 1 commits scanned. + [INFO] [secrets] [2023-09-04T03:46:36Z] ▶ 3:46AM INF scan completed in 60ms + [INFO] [secrets] [2023-09-04T03:46:36Z] ▶ 3:46AM WRN leaks found: 1 + ``` + +You've seen the policy work for one project. Create another project and apply the same policy. + +## Create project B + +To create project B: + +1. On the left sidebar, select **Search or go to** and find your group. +1. Select **New project**. +1. Select **Create blank project**. +1. Complete the fields. For **Project name**, enter `go-example-b`. +1. Select **Create project**. +1. Select **Add (`+`) > New file**. +1. Enter `helloworld.go` in the filename. +1. Copy and paste the following example Go code into the file. + + ```go + package main + import "fmt" + func main() { + fmt.Println("Hello world") + } + ``` + +1. Select **Commit changes**. + +Now that you have another project, you link it to the same policy project. + +## Link project B to the security policy project + +To link project B to the security policy project: + +1. On the left sidebar, select **Search or go to** and find the `go-example-b` project. +1. Go to **Secure > Policies**. +1. Select **Edit policy project**. +1. Select the dropdown list, then search for the security policy project created at the start of + this tutorial. +1. Select **Save**. + +Linking project B to the same policy project resulted in the same policy being applied. A scan +execution policy runs a secret detection scan on every MR, for any branch. Let's test the +policy by creating an MR in project B. + +## Test the scan execution policy with project B + +To test the scan execution policy: + +1. On the left sidebar, select **Search or go to** and find the `go-example-b` project. +1. Go to **Code > Repository**. +1. Select the `helloworld.go` file. +1. Select **Edit > Edit single file**. +1. Add the following line immediately after the `fmt.Println("hello world")` line: + + ```plaintext + var AdobeClient = "4ab4b080d9ce4072a6be2629c399d653" + ``` + +1. In the **Target Branch** field, enter `feature-b`. +1. Select **Commit changes**. +1. When the merge request page opens, select **Create merge request**. + + Let's check if the scan execution policy worked. Remember that we specified that secret detection + is to run every time a pipeline runs, for any branch. + +1. In the merge request just created, go the **Pipelines** tab and select the created pipeline. + +1. In the merge request just created, select the pipeline's ID. + + Here you can see that a secret detection job ran. Let's check if it detected the test secret. + +1. Select the secret detection job. + + Near the bottom of the job's log, the following output confirms that the example secret was detected. + + ```plaintext + [INFO] [secrets] [2023-09-04T04:22:28Z] ▶ 4:22AM INF 1 commits scanned. + [INFO] [secrets] [2023-09-04T04:22:28Z] ▶ 4:22AM INF scan completed in 58.2ms + [INFO] [secrets] [2023-09-04T04:22:28Z] ▶ 4:22AM WRN leaks found: 1 + ``` + +Congratulations. You've learned how to create a scan execution policy and enforce it on projects. diff --git a/doc/tutorials/secure_application.md b/doc/tutorials/secure_application.md index 96a4107e36c..606ca4d2909 100644 --- a/doc/tutorials/secure_application.md +++ b/doc/tutorials/secure_application.md @@ -14,6 +14,7 @@ GitLab can check your application for security vulnerabilities and that it meets | [Export Dependency List in SBOM format](export_sbom.md) | Learn how to export an application's dependencies to the CycloneDX SBOM format. | **{star}** | | [Create a compliance pipeline](compliance_pipeline/index.md) | Learn how to create compliance pipelines for your groups. | **{star}** | | [Set up a scan result policy](scan_result_policy/index.md) | Learn how to configure a scan result policy that takes action based on scan results. | **{star}** | +| [Set up a scan execution policy](scan_execution_policy/index.md) | Learn how to create a scan execution policy to enforce security scanning of your project. | **{star}** | | [Scan a Docker container for vulnerabilities](container_scanning/index.md) | Learn how to use container scanning templates to add container scanning to your projects. | **{star}** | | [Get started with GitLab application security](../user/application_security/get-started-security.md) | Follow recommended steps to set up security tools. | | | [GitLab Security Essentials](https://levelup.gitlab.com/courses/security-essentials) | Learn about the essential security capabilities of GitLab in this self-paced course. | | diff --git a/doc/user/analytics/dora_metrics.md b/doc/user/analytics/dora_metrics.md index 759b95bba56..391a1c7965f 100644 --- a/doc/user/analytics/dora_metrics.md +++ b/doc/user/analytics/dora_metrics.md @@ -144,6 +144,24 @@ The table below provides an overview of the DORA metrics' data aggregation in di | Time to restore service | Number of seconds an incident was open for | daily median per month | daily median | `day` (default) or `month` | | Change failure rate | percentage of deployments that cause an incident in production | daily median per month | percentage of failed deployments | `day` (default) or `month` | +## Configure DORA metrics calculation **(ULTIMATE ALL BETA)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96561) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `dora_configuration`. Disabled by default. This feature is in [Beta](../../policy/experiment-beta-support.md). + +FLAG: +On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, an administrator can [enable the feature flag](../../administration/feature_flags.md) named `dora_configuration`. +On GitLab.com, this feature is not available. +This feature is not ready for production use. + +You can configure the behavior of DORA metrics calculations. +To do this, in the Rails console run the following command: + +```ruby +Dora::Configuration.create!(project: my_project, ltfc_target_branches: \['master', 'main'\]) +``` + +This feature is in [Beta](../../policy/experiment-beta-support.md). + ## Retrieve DORA metrics data To retrieve DORA data, use the [GraphQL](../../api/graphql/reference/index.md) or the [REST](../../api/dora/metrics.md) APIs. diff --git a/doc/user/project/service_desk/configure.md b/doc/user/project/service_desk/configure.md index 3c4efd05901..817bb5e5066 100644 --- a/doc/user/project/service_desk/configure.md +++ b/doc/user/project/service_desk/configure.md @@ -167,6 +167,9 @@ named `service_desk_custom_email`. On GitLab.com, this feature is not available. Configure a custom email address to show as the sender of your support communication. Maintain brand identity and instill confidence among support requesters with a domain they recognize. +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For an overview, see [a short showcase video](https://youtu.be/_moD5U3xcQs). + This feature is in [Beta](../../../policy/experiment-beta-support.md#beta). A Beta feature is not production-ready, but is unlikely to change drastically before it's released. We encourage users to try Beta features and provide feedback diff --git a/lib/api/commits.rb b/lib/api/commits.rb index a4e1e8308c3..069d117db17 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -41,7 +41,7 @@ module API namespace: namespace, user: current_user, label: 'counts.web_ide_commits', - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: 'counts.web_ide_commits').to_context] + context: [Gitlab::Usage::MetricDefinition.context_for('counts.web_ide_commits').to_context] ) end end diff --git a/lib/api/helpers/packages_helpers.rb b/lib/api/helpers/packages_helpers.rb index f3b3a299204..6529bb43993 100644 --- a/lib/api/helpers/packages_helpers.rb +++ b/lib/api/helpers/packages_helpers.rb @@ -118,10 +118,7 @@ module API def track_snowplow_event(action_name, category, args) event_name = "i_package_#{action_name}" key_path = "counts.package_events_i_package_#{action_name}" - service_ping_context = Gitlab::Tracking::ServicePingContext.new( - data_source: :redis, - key_path: key_path - ).to_context + service_ping_context = Gitlab::Usage::MetricDefinition.context_for(key_path).to_context Gitlab::Tracking.event( category, diff --git a/lib/gitlab/event_store/store.rb b/lib/gitlab/event_store/store.rb index 2e5e0215687..318745cc192 100644 --- a/lib/gitlab/event_store/store.rb +++ b/lib/gitlab/event_store/store.rb @@ -15,12 +15,12 @@ module Gitlab lock! end - def subscribe(worker, to:, if: nil) + def subscribe(worker, to:, if: nil, delay: nil) condition = binding.local_variable_get('if') Array(to).each do |event| validate_subscription!(worker, event) - subscriptions[event] << Gitlab::EventStore::Subscription.new(worker, condition) + subscriptions[event] << Gitlab::EventStore::Subscription.new(worker, condition, delay) end end diff --git a/lib/gitlab/event_store/subscription.rb b/lib/gitlab/event_store/subscription.rb index 01986355d2d..81a65f9a8ff 100644 --- a/lib/gitlab/event_store/subscription.rb +++ b/lib/gitlab/event_store/subscription.rb @@ -3,17 +3,22 @@ module Gitlab module EventStore class Subscription - attr_reader :worker, :condition + attr_reader :worker, :condition, :delay - def initialize(worker, condition) + def initialize(worker, condition, delay) @worker = worker @condition = condition + @delay = delay end def consume_event(event) return unless condition_met?(event) - worker.perform_async(event.class.name, event.data.deep_stringify_keys) + if delay + worker.perform_in(delay, event.class.name, event.data.deep_stringify_keys) + else + worker.perform_async(event.class.name, event.data.deep_stringify_keys) + end # We rescue and track any exceptions here because we don't want to # impact other subscribers if one is faulty. diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 6b154c7033f..f8e7e66a8a5 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -48,24 +48,24 @@ module Gitlab 'de' => 96, 'en' => 100, 'eo' => 0, - 'es' => 29, + 'es' => 28, 'fil_PH' => 0, 'fr' => 99, 'gl_ES' => 0, 'id_ID' => 0, 'it' => 1, 'ja' => 99, - 'ko' => 20, + 'ko' => 23, 'nb_NO' => 21, 'nl_NL' => 0, 'pl_PL' => 3, 'pt_BR' => 55, - 'ro_RO' => 78, + 'ro_RO' => 76, 'ru' => 22, - 'si_LK' => 9, - 'tr_TR' => 9, - 'uk' => 52, - 'zh_CN' => 98, + 'si_LK' => 12, + 'tr_TR' => 8, + 'uk' => 51, + 'zh_CN' => 99, 'zh_HK' => 1, 'zh_TW' => 99 }.freeze diff --git a/lib/gitlab/tracking/service_ping_context.rb b/lib/gitlab/tracking/service_ping_context.rb index d31ca69a10c..8bd4d7767f6 100644 --- a/lib/gitlab/tracking/service_ping_context.rb +++ b/lib/gitlab/tracking/service_ping_context.rb @@ -9,13 +9,12 @@ module Gitlab ALLOWED_SOURCES = [REDISHLL_SOURCE, REDIS_SOURCE].freeze - def initialize(data_source:, event: nil, key_path: nil) - check_configuration(data_source, event, key_path) + def initialize(data_source:, event: nil) + check_configuration(data_source, event) @payload = { data_source: data_source } - payload[:event_name] = event if data_source.eql? REDISHLL_SOURCE - payload[:key_path] = key_path if data_source.eql? REDIS_SOURCE + payload[:event_name] = event end def to_context @@ -33,18 +32,14 @@ module Gitlab attr_reader :payload - def check_configuration(data_source, event, key_path) - unless ALLOWED_SOURCES.include?(data_source) + def check_configuration(data_source, event) + unless ALLOWED_SOURCES.include?(data_source.to_sym) configuration_error("#{data_source} is not acceptable data source for ServicePingContext") end - if REDISHLL_SOURCE.eql?(data_source) && event.nil? - configuration_error("event attribute can not be missing for #{REDISHLL_SOURCE} data source") - end - - return unless REDIS_SOURCE.eql?(data_source) && key_path.nil? + return unless event.nil? - configuration_error("key_path attribute can not be missing for #{REDIS_SOURCE} data source") + configuration_error("event attribute is required") end def configuration_error(message) diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb index bd42586731e..5a321eb7a1a 100644 --- a/lib/gitlab/usage/metric_definition.rb +++ b/lib/gitlab/usage/metric_definition.rb @@ -26,6 +26,18 @@ module Gitlab events_from_new_structure || events_from_old_structure || {} end + def to_context + return unless %w[redis redis_hll].include?(data_source) + + event_name = if data_source == 'redis_hll' + options[:events].first + elsif data_source == 'redis' + Gitlab::Usage::Metrics::Instrumentations::RedisMetric.new(attributes).redis_key + end + + Gitlab::Tracking::ServicePingContext.new(data_source: data_source, event: event_name) + end + def to_h attributes end @@ -98,6 +110,10 @@ module Gitlab all.select { |definition| definition.attributes[:instrumentation_class].present? && definition.available? } end + def context_for(key_path) + definitions[key_path].to_context + end + def schemer @schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH)) end diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb index ca5e5b706c4..217fa6aca49 100644 --- a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb @@ -48,8 +48,6 @@ module Gitlab end end - private - def redis_key key = metric_event.dup key.prepend("#{prefix}_") if prefix diff --git a/spec/lib/api/helpers/packages_helpers_spec.rb b/spec/lib/api/helpers/packages_helpers_spec.rb index 6ba4396c396..bb7b9d688ea 100644 --- a/spec/lib/api/helpers/packages_helpers_spec.rb +++ b/spec/lib/api/helpers/packages_helpers_spec.rb @@ -292,7 +292,7 @@ RSpec.describe API::Helpers::PackagesHelpers, feature_category: :package_registr let(:label) { 'counts.package_events_i_package_push_package_by_deploy_token' } let(:property) { 'i_package_push_package_by_deploy_token' } let(:service_ping_context) do - [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: 'counts.package_events_i_package_push_package_by_deploy_token').to_h] + [Gitlab::Usage::MetricDefinition.context_for('counts.package_events_i_package_push_package_by_deploy_token').to_h] end it 'logs a snowplow event' do @@ -320,7 +320,7 @@ RSpec.describe API::Helpers::PackagesHelpers, feature_category: :package_registr let(:label) { 'counts.package_events_i_package_pull_package_by_guest' } let(:property) { 'i_package_pull_package_by_guest' } let(:service_ping_context) do - [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: 'counts.package_events_i_package_pull_package_by_guest').to_h] + [Gitlab::Usage::MetricDefinition.context_for('counts.package_events_i_package_pull_package_by_guest').to_h] end it 'logs a snowplow event' do diff --git a/spec/lib/gitlab/event_store/store_spec.rb b/spec/lib/gitlab/event_store/store_spec.rb index bbdfecc897a..04d0706c130 100644 --- a/spec/lib/gitlab/event_store/store_spec.rb +++ b/spec/lib/gitlab/event_store/store_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::EventStore::Store do +RSpec.describe Gitlab::EventStore::Store, feature_category: :shared do let(:event_klass) { stub_const('TestEvent', Class.new(Gitlab::EventStore::Event)) } let(:event) { event_klass.new(data: data) } let(:another_event_klass) { stub_const('TestAnotherEvent', Class.new(Gitlab::EventStore::Event)) } @@ -222,8 +222,6 @@ RSpec.describe Gitlab::EventStore::Store do end end - let(:event) { event_klass.new(data: data) } - it 'dispatches the event to the workers satisfying the condition' do expect(worker).to receive(:perform_async).with('TestEvent', serialized_data) expect(another_worker).not_to receive(:perform_async) @@ -232,6 +230,20 @@ RSpec.describe Gitlab::EventStore::Store do end end + context 'when subscription has delayed dispatching of event' do + let(:store) do + described_class.new do |s| + s.subscribe worker, to: event_klass, delay: 1.minute + end + end + + it 'dispatches the event to the worker after some time' do + expect(worker).to receive(:perform_in).with(1.minute, 'TestEvent', serialized_data) + + store.publish(event) + end + end + context 'when the event does not have any subscribers' do let(:store) do described_class.new do |s| @@ -239,8 +251,6 @@ RSpec.describe Gitlab::EventStore::Store do end end - let(:event) { event_klass.new(data: data) } - it 'returns successfully' do expect { store.publish(event) }.not_to raise_error end diff --git a/spec/lib/gitlab/tracking/service_ping_context_spec.rb b/spec/lib/gitlab/tracking/service_ping_context_spec.rb index 7530650b902..3da9a588c0e 100644 --- a/spec/lib/gitlab/tracking/service_ping_context_spec.rb +++ b/spec/lib/gitlab/tracking/service_ping_context_spec.rb @@ -7,29 +7,27 @@ RSpec.describe Gitlab::Tracking::ServicePingContext do using RSpec::Parameterized::TableSyntax context 'with valid configuration' do - where(:data_source, :event, :key_path) do - :redis | nil | 'counts.some_metric' - :redis_hll | 'some_event' | nil + where(:data_source, :event) do + :redis | 'some_event' + :redis_hll | 'some_event' end with_them do it 'does not raise errors' do - expect { described_class.new(data_source: data_source, event: event, key_path: key_path) }.not_to raise_error + expect { described_class.new(data_source: data_source, event: event) }.not_to raise_error end end end context 'with invalid configuration' do - where(:data_source, :event, :key_path) do - :redis | nil | nil - :redis | 'some_event' | nil - :redis_hll | nil | nil - :redis_hll | nil | 'some key_path' - :random | 'some_event' | nil + where(:data_source, :event) do + :redis | nil + :redis_hll | nil + :random | 'some_event' end with_them do - subject(:new_instance) { described_class.new(data_source: data_source, event: event, key_path: key_path) } + subject(:new_instance) { described_class.new(data_source: data_source, event: event) } it 'does not raise errors' do expect { new_instance }.to raise_error(ArgumentError) @@ -48,10 +46,10 @@ RSpec.describe Gitlab::Tracking::ServicePingContext do end context 'for redis data source' do - let(:context_instance) { described_class.new(data_source: :redis, key_path: 'counts.sample_metric') } + let(:context_instance) { described_class.new(data_source: :redis, event: 'some_event') } it 'contains event_name' do - expect(context_instance.to_context.to_json.dig(:data, :key_path)).to eq('counts.sample_metric') + expect(context_instance.to_context.to_json.dig(:data, :event_name)).to eq('some_event') end end end diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb index 859f3f7a8d7..283d76d731f 100644 --- a/spec/lib/gitlab/usage/metric_definition_spec.rb +++ b/spec/lib/gitlab/usage/metric_definition_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Usage::MetricDefinition do +RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping do let(:attributes) do { description: 'GitLab instance unique identifier', @@ -109,6 +109,42 @@ RSpec.describe Gitlab::Usage::MetricDefinition do end end + describe '#to_context' do + subject { definition.to_context } + + context 'with data_source redis_hll metric' do + before do + attributes[:data_source] = 'redis_hll' + attributes[:options] = { events: %w[some_event_1 some_event_2] } + end + + it 'returns a ServicePingContext with first event as event_name' do + expect(subject.to_h[:data][:event_name]).to eq('some_event_1') + end + end + + context 'with data_source redis metric' do + before do + attributes[:data_source] = 'redis' + attributes[:options] = { prefix: 'web_ide', event: 'views_count', include_usage_prefix: false } + end + + it 'returns a ServicePingContext with redis key as event_name' do + expect(subject.to_h[:data][:event_name]).to eq('WEB_IDE_VIEWS_COUNT') + end + end + + context 'with data_source database metric' do + before do + attributes[:data_source] = 'database' + end + + it 'returns nil' do + is_expected.to be_nil + end + end + end + describe '#validate' do using RSpec::Parameterized::TableSyntax diff --git a/spec/presenters/event_presenter_spec.rb b/spec/presenters/event_presenter_spec.rb index 9093791421d..3f34c96ad8e 100644 --- a/spec/presenters/event_presenter_spec.rb +++ b/spec/presenters/event_presenter_spec.rb @@ -76,4 +76,104 @@ RSpec.describe EventPresenter do .to have_attributes(note_target_type_name: 'issue') end end + + describe '#push_activity_description' do + subject { event.present.push_activity_description } + + context 'when event is a regular event' do + let(:event) { build(:event, project: project) } + + it { is_expected.to be_nil } + end + + context 'when event is a push event' do + let!(:push_event_payload) { build(:push_event_payload, event: event, ref_count: ref_count) } + let(:event) { build(:push_event, project: project) } + + context 'when it is an individual event' do + let(:ref_count) { nil } + + it { is_expected.to eq 'pushed to branch' } + end + + context 'when it is a batch event' do + let(:ref_count) { 1 } + + it { is_expected.to eq 'pushed to 1 branch' } + end + end + end + + describe '#batch_push?' do + subject { event.present.batch_push? } + + context 'when event is a regular event' do + let(:event) { build(:event, project: project) } + + it { is_expected.to be_falsey } + end + + context 'when event is a push event' do + let!(:push_event_payload) { build(:push_event_payload, event: event, ref_count: ref_count) } + let(:event) { build(:push_event, project: project) } + + context 'when it is an individual event' do + let(:ref_count) { nil } + + it { is_expected.to be_falsey } + end + + context 'when it is a batch event' do + let(:ref_count) { 1 } + + it { is_expected.to be_truthy } + end + end + end + + describe '#linked_to_reference?' do + subject { event.present.linked_to_reference? } + + context 'when event is a regular event' do + let(:event) { build(:event, project: project) } + + it { is_expected.to be_falsey } + end + + context 'when event is a push event' do + let!(:push_event_payload) { build(:push_event_payload, event: event, ref: ref, ref_type: ref_type) } + let(:ref) { 'master' } + let(:ref_type) { :branch } + + context 'when event belongs to group' do + let(:event) { build(:push_event, group: group) } + + it { is_expected.to be_falsey } + end + + context 'when event belongs to project' do + let(:event) { build(:push_event, project: project) } + + it { is_expected.to be_falsey } + + context 'when matching tag exists' do + let(:ref_type) { :tag } + + before do + allow(project.repository).to receive(:tag_exists?).with(ref).and_return(true) + end + + it { is_expected.to be_truthy } + end + + context 'when matching branch exists' do + before do + allow(project.repository).to receive(:branch_exists?).with(ref).and_return(true) + end + + it { is_expected.to be_truthy } + end + end + end + end end diff --git a/spec/rake_helper.rb b/spec/rake_helper.rb index 0386fef5134..53bd36542b7 100644 --- a/spec/rake_helper.rb +++ b/spec/rake_helper.rb @@ -6,7 +6,7 @@ require 'rake' RSpec.configure do |config| config.include RakeHelpers - config.before(:all) do + config.before(:all, type: :task) do Rake.application.rake_require 'tasks/gitlab/helpers' Rake::Task.define_task :environment end diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 687ce333ca5..8b9ac7cd588 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -589,7 +589,7 @@ RSpec.describe API::Commits, feature_category: :source_code_management do let(:namespace) { project.namespace.reload } let(:label) { 'counts.web_ide_commits' } let(:context) do - [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: 'counts.web_ide_commits').to_context.to_json] + [Gitlab::Usage::MetricDefinition.context_for('counts.web_ide_commits').to_context.to_json] end end end diff --git a/spec/requests/api/usage_data_queries_spec.rb b/spec/requests/api/usage_data_queries_spec.rb index 584b0f31a07..385241e62e7 100644 --- a/spec/requests/api/usage_data_queries_spec.rb +++ b/spec/requests/api/usage_data_queries_spec.rb @@ -70,7 +70,7 @@ RSpec.describe API::UsageDataQueries, :aggregate_failures, feature_category: :se end end - context 'when querying sql metrics' do + context 'when querying sql metrics', type: :task do let(:file) { Rails.root.join('tmp', 'test', 'sql_metrics_queries.json') } before do diff --git a/spec/services/merge_requests/create_ref_service_spec.rb b/spec/services/merge_requests/create_ref_service_spec.rb index 5eb6bb8a7c2..5f7b9430416 100644 --- a/spec/services/merge_requests/create_ref_service_spec.rb +++ b/spec/services/merge_requests/create_ref_service_spec.rb @@ -85,17 +85,6 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains ) end - context 'when the merge request fails to save' do - before do - allow(merge_request).to receive(:save!).and_raise(ActiveRecord::StatementTimeout) - end - - it 'returns an error response' do - expect(result[:status]).to eq :error - expect(result[:message]).to eq 'Failed to update merge params' - end - end - shared_examples_for 'writing with a merge commit' do it 'merges with a merge commit', :aggregate_failures do expect(result[:status]).to eq :success @@ -104,10 +93,6 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(result[:merge_commit_sha]).to be_present expect(result[:squash_commit_sha]).not_to be_present - expect(merge_request.reload.merge_params['train_ref']).to( - eq({ 'commit_sha' => result[:commit_sha], - 'merge_commit_sha' => result[:merge_commit_sha] }) - ) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( [ @@ -130,11 +115,6 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(result[:merge_commit_sha]).to be_present expect(result[:squash_commit_sha]).to be_present - expect(merge_request.reload.merge_params['train_ref']).to( - eq({ 'commit_sha' => result[:commit_sha], - 'merge_commit_sha' => result[:merge_commit_sha], - 'squash_commit_sha' => result[:squash_commit_sha] }) - ) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( [ @@ -156,10 +136,6 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(result[:merge_commit_sha]).not_to be_present expect(result[:squash_commit_sha]).to be_present - expect(merge_request.reload.merge_params['train_ref']).to( - eq({ 'commit_sha' => result[:commit_sha], - 'squash_commit_sha' => result[:squash_commit_sha] }) - ) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( [ @@ -180,7 +156,6 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(result[:merge_commit_sha]).not_to be_present expect(result[:squash_commit_sha]).not_to be_present - expect(merge_request.reload.merge_params['train_ref']).to eq({ 'commit_sha' => result[:commit_sha] }) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( eq( [ diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 6917feaeaff..6e34f4362c1 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -103,10 +103,11 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf end context 'when merge strategy is merge commit' do - it 'persists merge_commit_sha and nullifies in_progress_merge_commit_sha' do + it 'persists merge_commit_sha and merged_commit_sha and nullifies in_progress_merge_commit_sha' do service.execute(merge_request) expect(merge_request.merge_commit_sha).not_to be_nil + expect(merge_request.merged_commit_sha).to eq merge_request.merge_commit_sha expect(merge_request.in_progress_merge_commit_sha).to be_nil end @@ -130,16 +131,18 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf ) end - it 'does not create merge_commit_sha and nullifies in_progress_merge_commit_sha' do + it 'does not create merge_commit_sha, but persists merged_commit_sha and nullifies in_progress_merge_commit_sha' do service.execute(merge_request) expect(merge_request.merge_commit_sha).to be_nil + expect(merge_request.merged_commit_sha).not_to be_nil + expect(merge_request.merged_commit_sha).to eq merge_request.diff_head_sha expect(merge_request.in_progress_merge_commit_sha).to be_nil end it_behaves_like 'with valid params' - it 'updates squash_commit_sha if it is a squash' do + it 'updates squash_commit_sha and merged_commit_sha if it is a squash' do expect(merge_request).to receive(:update_and_mark_in_progress_merge_commit_sha).twice.and_call_original merge_request.update!(squash: true) @@ -149,6 +152,7 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf .from(nil) expect(merge_request.merge_commit_sha).to be_nil + expect(merge_request.merged_commit_sha).to eq merge_request.squash_commit_sha expect(merge_request.in_progress_merge_commit_sha).to be_nil end end diff --git a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb index 3d3b619451d..29d6f202498 100644 --- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb +++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb @@ -57,7 +57,7 @@ RSpec.shared_examples 'Snowplow event tracking with Redis context' do |overrides it_behaves_like 'Snowplow event tracking', overrides: overrides do let(:context) do key_path = try(:label) || action - [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: key_path).to_context.to_json] + [Gitlab::Usage::MetricDefinition.context_for(key_path).to_context.to_json] end end end diff --git a/spec/tasks/gitlab/audit_event_types/check_docs_task_spec.rb b/spec/tasks/gitlab/audit_event_types/check_docs_task_spec.rb index 16cd8c92273..b492289e99e 100644 --- a/spec/tasks/gitlab/audit_event_types/check_docs_task_spec.rb +++ b/spec/tasks/gitlab/audit_event_types/check_docs_task_spec.rb @@ -5,9 +5,9 @@ require_relative '../../../../lib/tasks/gitlab/audit_event_types/check_docs_task require_relative '../../../../lib/tasks/gitlab/audit_event_types/compile_docs_task' RSpec.describe Tasks::Gitlab::AuditEventTypes::CheckDocsTask, feature_category: :audit_events do - let_it_be(:docs_dir) { Rails.root.join("tmp/tests/doc/administration/audit_event_streaming") } - let_it_be(:docs_path) { Rails.root.join(docs_dir, 'audit_event_types.md') } - let_it_be(:template_erb_path) { Rails.root.join("tooling/audit_events/docs/templates/audit_event_types.md.erb") } + let(:docs_dir) { Rails.root.join("tmp/tests/doc/administration/audit_event_streaming") } + let(:docs_path) { Rails.root.join(docs_dir, 'audit_event_types.md') } + let(:template_erb_path) { Rails.root.join("tooling/audit_events/docs/templates/audit_event_types.md.erb") } subject(:check_docs_task) { described_class.new(docs_dir, docs_path, template_erb_path) } @@ -37,7 +37,7 @@ RSpec.describe Tasks::Gitlab::AuditEventTypes::CheckDocsTask, feature_category: end context 'when an existing audit event type is removed' do - let_it_be(:updated_definition) { Gitlab::Audit::Type::Definition.definitions.except(:feature_flag_created) } + let(:updated_definition) { Gitlab::Audit::Type::Definition.definitions.except(:feature_flag_created) } it 'raises an error' do expect(Gitlab::Audit::Type::Definition).to receive(:definitions).and_return(updated_definition) @@ -50,7 +50,7 @@ RSpec.describe Tasks::Gitlab::AuditEventTypes::CheckDocsTask, feature_category: end context 'when an existing audit event type is updated' do - let_it_be(:updated_definition) { Gitlab::Audit::Type::Definition.definitions } + let(:updated_definition) { Gitlab::Audit::Type::Definition.definitions } it 'raises an error' do updated_definition[:feature_flag_created].attributes[:streamed] = false diff --git a/spec/tasks/gitlab/audit_event_types/compile_docs_task_spec.rb b/spec/tasks/gitlab/audit_event_types/compile_docs_task_spec.rb index da8dd170bec..0ee85b1283b 100644 --- a/spec/tasks/gitlab/audit_event_types/compile_docs_task_spec.rb +++ b/spec/tasks/gitlab/audit_event_types/compile_docs_task_spec.rb @@ -4,9 +4,9 @@ require 'rake_helper' require_relative '../../../../lib/tasks/gitlab/audit_event_types/compile_docs_task' RSpec.describe Tasks::Gitlab::AuditEventTypes::CompileDocsTask, feature_category: :audit_events do - let_it_be(:docs_dir) { Rails.root.join("tmp/tests/doc/administration/audit_event_streaming") } - let_it_be(:docs_path) { Rails.root.join(docs_dir, 'audit_event_types.md') } - let_it_be(:template_erb_path) { Rails.root.join("tooling/audit_events/docs/templates/audit_event_types.md.erb") } + let(:docs_dir) { Rails.root.join("tmp/tests/doc/administration/audit_event_streaming") } + let(:docs_path) { Rails.root.join(docs_dir, 'audit_event_types.md') } + let(:template_erb_path) { Rails.root.join("tooling/audit_events/docs/templates/audit_event_types.md.erb") } subject(:compile_docs_task) { described_class.new(docs_dir, docs_path, template_erb_path) } diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index fad36ad6f2a..fda27d5827f 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -38,7 +38,7 @@ RSpec.describe 'gitlab:backup namespace rake tasks', :delete, feature_category: %w[db repositories] end - before(:all) do # rubocop:disable RSpec/BeforeAll + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/gitlab/backup' Rake.application.rake_require 'tasks/gitlab/shell' diff --git a/spec/tasks/gitlab/ci_secure_files/check_rake_spec.rb b/spec/tasks/gitlab/ci_secure_files/check_rake_spec.rb index b3bd6be8fde..fc9aae3597e 100644 --- a/spec/tasks/gitlab/ci_secure_files/check_rake_spec.rb +++ b/spec/tasks/gitlab/ci_secure_files/check_rake_spec.rb @@ -4,7 +4,7 @@ require 'rake_helper' RSpec.describe 'gitlab:ci_secure_files', factory_default: :keep, feature_category: :mobile_devops do describe 'check' do - let_it_be(:project) { create_default(:project).freeze } + let!(:project) { create_default(:project).freeze } let!(:secure_file) { create(:ci_secure_file) } before do diff --git a/spec/tasks/gitlab/ci_secure_files/migrate_rake_spec.rb b/spec/tasks/gitlab/ci_secure_files/migrate_rake_spec.rb index 37ae0d694eb..f3856969a6e 100644 --- a/spec/tasks/gitlab/ci_secure_files/migrate_rake_spec.rb +++ b/spec/tasks/gitlab/ci_secure_files/migrate_rake_spec.rb @@ -3,12 +3,12 @@ require 'rake_helper' RSpec.describe 'gitlab:ci_secure_files', feature_category: :mobile_devops do - let_it_be(:local_file) { create(:ci_secure_file) } + let!(:local_file) { create(:ci_secure_file) } let(:logger) { instance_double(Logger) } let(:helper) { double } - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/ci_secure_files/migrate' end diff --git a/spec/tasks/gitlab/container_registry_rake_spec.rb b/spec/tasks/gitlab/container_registry_rake_spec.rb index f4bd8560cd0..d0c728bf36d 100644 --- a/spec/tasks/gitlab/container_registry_rake_spec.rb +++ b/spec/tasks/gitlab/container_registry_rake_spec.rb @@ -3,9 +3,9 @@ require 'rake_helper' RSpec.describe 'gitlab:container_registry namespace rake tasks', :silence_stdout do - let_it_be(:api_url) { 'http://registry.gitlab' } + let(:api_url) { 'http://registry.gitlab' } - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/container_registry' end diff --git a/spec/tasks/gitlab/db/cells/bump_cell_sequences_rake_spec.rb b/spec/tasks/gitlab/db/cells/bump_cell_sequences_rake_spec.rb index a5dd7c0ff09..a1725d6fed7 100644 --- a/spec/tasks/gitlab/db/cells/bump_cell_sequences_rake_spec.rb +++ b/spec/tasks/gitlab/db/cells/bump_cell_sequences_rake_spec.rb @@ -4,7 +4,7 @@ require 'rake_helper' RSpec.describe 'gitlab:db:cells:bump_cell_sequences', :silence_stdout, :suppress_gitlab_schemas_validate_connection, feature_category: :cell, query_analyzers: false do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/db/cells/bump_cell_sequences' # empty task as env is already loaded diff --git a/spec/tasks/gitlab/db/decomposition/connection_status_rake_spec.rb b/spec/tasks/gitlab/db/decomposition/connection_status_rake_spec.rb index 5116ee5663e..352e3d944fc 100644 --- a/spec/tasks/gitlab/db/decomposition/connection_status_rake_spec.rb +++ b/spec/tasks/gitlab/db/decomposition/connection_status_rake_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'gitlab:db:decomposition:connection_status', feature_category: :c subject { run_rake_task('gitlab:db:decomposition:connection_status') } - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/db/decomposition/connection_status' end diff --git a/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb b/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb index f923d09bdaa..3d4b977644f 100644 --- a/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb +++ b/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb @@ -4,7 +4,7 @@ require 'rake_helper' RSpec.describe 'gitlab:db:decomposition:rollback:bump_ci_sequences', :silence_stdout, :suppress_gitlab_schemas_validate_connection, feature_category: :cell, query_analyzers: false do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/db/decomposition/rollback/bump_ci_sequences' # empty task as env is already loaded diff --git a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb index 069f5dc7d84..5baf13b9847 100644 --- a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb +++ b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:db:lock_writes', :reestablished_active_record_base, feature_category: :cell do - before_all do + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/seed_fu' Rake.application.rake_require 'tasks/gitlab/db/validate_config' diff --git a/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb b/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb index 41d77d6efc7..9a101921b68 100644 --- a/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb +++ b/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'migration_fix_15_11', :reestablished_active_record_base, feature let(:target_init_schema) { '20220314184009' } let(:earlier_init_schema) { '20210101010101' } - before_all do + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/gitlab/db/migration_fix_15_11' diff --git a/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb b/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb index 78d2bcba8a2..518acfc5d81 100644 --- a/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb +++ b/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb @@ -9,7 +9,7 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish let(:test_gitlab_main_table) { '_test_gitlab_main_table' } let(:test_gitlab_ci_table) { '_test_gitlab_ci_table' } - before_all do + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/seed_fu' Rake.application.rake_require 'tasks/gitlab/db/validate_config' diff --git a/spec/tasks/gitlab/db/validate_config_rake_spec.rb b/spec/tasks/gitlab/db/validate_config_rake_spec.rb index e2e1cf249f0..e58667578b2 100644 --- a/spec/tasks/gitlab/db/validate_config_rake_spec.rb +++ b/spec/tasks/gitlab/db/validate_config_rake_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'gitlab:db:validate_config', :silence_stdout, :suppress_gitlab_sc # which would not be cleaned either by `DbCleaner` self.use_transactional_tests = false - before_all do + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/seed_fu' Rake.application.rake_require 'tasks/gitlab/db/validate_config' diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb index 3f4cc740954..c35c162c99a 100644 --- a/spec/tasks/gitlab/db_rake_spec.rb +++ b/spec/tasks/gitlab/db_rake_spec.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' -require 'rake' +require 'rake_helper' RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_category: :database do - before(:all) do # rubocop:disable RSpec/BeforeAll + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/seed_fu' Rake.application.rake_require 'tasks/gitlab/db' @@ -552,9 +551,9 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor end describe 'clean_structure_sql' do - let_it_be(:clean_rake_task) { 'gitlab:db:clean_structure_sql' } - let_it_be(:test_task_name) { 'gitlab:db:_test_multiple_structure_cleans' } - let_it_be(:input) { 'this is structure data' } + let(:clean_rake_task) { 'gitlab:db:clean_structure_sql' } + let(:test_task_name) { 'gitlab:db:_test_multiple_structure_cleans' } + let(:input) { 'this is structure data' } let(:output) { StringIO.new } diff --git a/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb b/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb index e1504a8aaf5..0bda879bd7c 100644 --- a/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb +++ b/spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:dependency_proxy namespace rake task', :silence_stdout do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/dependency_proxy/migrate' end diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index 7eca2773cf2..5a395c8f6ef 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/gitaly' end diff --git a/spec/tasks/gitlab/lfs/migrate_rake_spec.rb b/spec/tasks/gitlab/lfs/migrate_rake_spec.rb index 09c95783867..cbc39c6b093 100644 --- a/spec/tasks/gitlab/lfs/migrate_rake_spec.rb +++ b/spec/tasks/gitlab/lfs/migrate_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:lfs namespace rake task', :silence_stdout do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/lfs/migrate' end diff --git a/spec/tasks/gitlab/packages/migrate_rake_spec.rb b/spec/tasks/gitlab/packages/migrate_rake_spec.rb index be69990a745..cdc817cdf38 100644 --- a/spec/tasks/gitlab/packages/migrate_rake_spec.rb +++ b/spec/tasks/gitlab/packages/migrate_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:packages namespace rake task', :silence_stdout do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/packages/migrate' end diff --git a/spec/tasks/gitlab/password_rake_spec.rb b/spec/tasks/gitlab/password_rake_spec.rb index 5d5e5af2536..21a6dc102e6 100644 --- a/spec/tasks/gitlab/password_rake_spec.rb +++ b/spec/tasks/gitlab/password_rake_spec.rb @@ -3,8 +3,8 @@ require 'rake_helper' RSpec.describe 'gitlab:password rake tasks', :silence_stdout do - let_it_be(:user_1) { create(:user, username: 'foobar', password: User.random_password) } - let_it_be(:password) { User.random_password } + let!(:user_1) { create(:user, username: 'foobar', password: User.random_password) } + let(:password) { User.random_password } def stub_username(username) allow(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ').and_return(username) diff --git a/spec/tasks/gitlab/refresh_project_statistics_build_artifacts_size_rake_spec.rb b/spec/tasks/gitlab/refresh_project_statistics_build_artifacts_size_rake_spec.rb index f0fc3c501c5..60c0d80223e 100644 --- a/spec/tasks/gitlab/refresh_project_statistics_build_artifacts_size_rake_spec.rb +++ b/spec/tasks/gitlab/refresh_project_statistics_build_artifacts_size_rake_spec.rb @@ -6,9 +6,9 @@ RSpec.describe 'gitlab:refresh_project_statistics_build_artifacts_size rake task let(:rake_task) { 'gitlab:refresh_project_statistics_build_artifacts_size' } describe 'enqueuing build artifacts size statistics refresh for given list of project IDs' do - let_it_be(:project_1) { create(:project) } - let_it_be(:project_2) { create(:project) } - let_it_be(:project_3) { create(:project) } + let!(:project_1) { create(:project) } + let!(:project_2) { create(:project) } + let!(:project_3) { create(:project) } let(:csv_body) do <<~BODY diff --git a/spec/tasks/gitlab/snippets_rake_spec.rb b/spec/tasks/gitlab/snippets_rake_spec.rb index f0ba5ac2d92..231c2dae006 100644 --- a/spec/tasks/gitlab/snippets_rake_spec.rb +++ b/spec/tasks/gitlab/snippets_rake_spec.rb @@ -3,13 +3,13 @@ require 'rake_helper' RSpec.describe 'gitlab:snippets namespace rake task', :silence_stdout do - let_it_be(:user) { create(:user) } - let_it_be(:migrated) { create(:personal_snippet, :repository, author: user) } + let!(:user) { create(:user) } + let!(:migrated) { create(:personal_snippet, :repository, author: user) } let(:non_migrated) { create_list(:personal_snippet, 3, author: user) } let(:non_migrated_ids) { non_migrated.pluck(:id) } - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/snippets' end diff --git a/spec/tasks/gitlab/terraform/migrate_rake_spec.rb b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb index 0547d351065..3797c01a9cb 100644 --- a/spec/tasks/gitlab/terraform/migrate_rake_spec.rb +++ b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb @@ -3,12 +3,12 @@ require 'rake_helper' RSpec.describe 'gitlab:terraform_states', :silence_stdout do - let_it_be(:version) { create(:terraform_state_version) } + let!(:version) { create(:terraform_state_version) } let(:logger) { instance_double(Logger) } let(:helper) { double } - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/terraform/migrate' end diff --git a/spec/tasks/gitlab/web_hook_rake_spec.rb b/spec/tasks/gitlab/web_hook_rake_spec.rb index cb6a6e72ab1..6ad65f55142 100644 --- a/spec/tasks/gitlab/web_hook_rake_spec.rb +++ b/spec/tasks/gitlab/web_hook_rake_spec.rb @@ -3,10 +3,10 @@ require 'rake_helper' RSpec.describe 'gitlab:web_hook namespace rake tasks', :silence_stdout do - let_it_be(:group, refind: true) { create(:group) } - let_it_be(:project1, reload: true) { create(:project, namespace: group) } - let_it_be(:project2, reload: true) { create(:project, namespace: group) } - let_it_be(:other_group_project, reload: true) { create(:project) } + let!(:group) { create(:group) } + let!(:project1) { create(:project, namespace: group) } + let!(:project2) { create(:project, namespace: group) } + let!(:other_group_project) { create(:project) } let(:url) { 'http://example.com' } let(:hook_urls) { (project1.hooks + project2.hooks).map(&:url) } diff --git a/spec/tasks/gitlab/workhorse_rake_spec.rb b/spec/tasks/gitlab/workhorse_rake_spec.rb index 17f3133ecdc..e87bef9f01f 100644 --- a/spec/tasks/gitlab/workhorse_rake_spec.rb +++ b/spec/tasks/gitlab/workhorse_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:workhorse namespace rake task', :silence_stdout, feature_category: :source_code_management do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/workhorse' end diff --git a/spec/tasks/gitlab/x509/update_rake_spec.rb b/spec/tasks/gitlab/x509/update_rake_spec.rb index abf8316d978..118b0b2b960 100644 --- a/spec/tasks/gitlab/x509/update_rake_spec.rb +++ b/spec/tasks/gitlab/x509/update_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:x509 namespace rake task', :silence_stdout do - before_all do + before(:all) do Rake.application.rake_require 'tasks/gitlab/x509/update' end diff --git a/spec/tasks/migrate/schema_check_rake_spec.rb b/spec/tasks/migrate/schema_check_rake_spec.rb index 5afad752982..4d0f59295a6 100644 --- a/spec/tasks/migrate/schema_check_rake_spec.rb +++ b/spec/tasks/migrate/schema_check_rake_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'schema_version_check rake task', :silence_stdout do include StubENV let(:valid_schema_version) { 20211004170422 } - before_all do + before(:all) do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/migrate/schema_check' diff --git a/spec/views/events/event/_push.html.haml_spec.rb b/spec/views/events/event/_push.html.haml_spec.rb index f4d3258ff67..fe4357d3ad5 100644 --- a/spec/views/events/event/_push.html.haml_spec.rb +++ b/spec/views/events/event/_push.html.haml_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'events/event/_push.html.haml' do let(:event) { build_stubbed(:push_event) } + let(:event_presenter) { event.present } context 'with a branch' do let(:payload) { build_stubbed(:push_event_payload, event: event) } @@ -16,14 +17,14 @@ RSpec.describe 'events/event/_push.html.haml' do allow(event.project.repository).to receive(:branch_exists?).with(event.ref_name).and_return(true) link = project_commits_path(event.project, event.ref_name) - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).to have_link(event.ref_name, href: link) end context 'that has been deleted' do it 'does not link to the branch' do - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).not_to have_link(event.ref_name) end @@ -40,7 +41,7 @@ RSpec.describe 'events/event/_push.html.haml' do end it 'includes the count in the text' do - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).to include('4 branches') end @@ -58,14 +59,14 @@ RSpec.describe 'events/event/_push.html.haml' do allow(event.project.repository).to receive(:tag_exists?).with(event.ref_name).and_return(true) link = project_commits_path(event.project, event.ref_name) - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).to have_link(event.ref_name, href: link) end context 'that has been deleted' do it 'does not link to the tag' do - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).not_to have_link(event.ref_name) end @@ -82,7 +83,7 @@ RSpec.describe 'events/event/_push.html.haml' do end it 'includes the count in the text' do - render partial: 'events/event/push', locals: { event: event } + render partial: 'events/event/push', locals: { event: event_presenter } expect(rendered).to include('4 tags') end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 5c8a75aca3f..2e0a2535453 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -282,7 +282,7 @@ RSpec.describe PostReceive, feature_category: :source_code_management do let(:user) { project.creator } let(:label) { 'counts.source_code_pushes' } let(:property) { 'source_code_pushes' } - let(:context) { [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: label).to_h] } + let(:context) { [Gitlab::Usage::MetricDefinition.context_for(label).to_h] } subject(:post_receive) { perform } end diff --git a/vendor/project_templates/typo3_distribution.tar.gz b/vendor/project_templates/typo3_distribution.tar.gz Binary files differindex 1de92d781af..b25f949011f 100644 --- a/vendor/project_templates/typo3_distribution.tar.gz +++ b/vendor/project_templates/typo3_distribution.tar.gz |