diff options
| author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-13 12:09:26 +0000 |
|---|---|---|
| committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-13 12:09:26 +0000 |
| commit | 9fdb3dbd6bacb125d40290aac8409da2f9fe19fc (patch) | |
| tree | 532a0cfc06fa0f4c1d718a33804e6bbf2b650e70 | |
| parent | 2d8c28f1d32709280506507f3b6e6d2da7440da9 (diff) | |
| download | gitlab-ce-9fdb3dbd6bacb125d40290aac8409da2f9fe19fc.tar.gz | |
Add latest changes from gitlab-org/gitlab@master
91 files changed, 1313 insertions, 157 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 29a0b7617e7..e523c42f430 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -169,6 +169,7 @@ Naming/FileName: - 'qa/tasks/**/*.rake' - '**/*.ru' - 'app/graphql/types/issue_connection.rb' + - 'app/graphql/types/group_connection.rb' IgnoreExecutableScripts: true AllowedAcronyms: diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index e14018cce66..f4be1450bea 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -c2dd35e7775018bd29c2b1306afeee966ba3b4d7 +cf32d208912de9dfbfdd4baab42655baf82bfce5 @@ -353,7 +353,7 @@ gem 'snowplow-tracker', '~> 0.6.1' # Metrics gem 'webrick', '~> 1.6.1', require: false -gem 'prometheus-client-mmap', '~> 0.16', require: 'prometheus/client' +gem 'prometheus-client-mmap', '~> 0.17', require: 'prometheus/client' gem 'warning', '~> 1.3.0' diff --git a/Gemfile.checksum b/Gemfile.checksum index 5df02c1e9df..9c3173f19f4 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -428,7 +428,7 @@ {"name":"premailer","version":"1.16.0","platform":"ruby","checksum":"03e4402c448e6bae13fb5f6301a8bde4f3508e1bff90ae7c0972c7be94694786"}, {"name":"premailer-rails","version":"1.10.3","platform":"ruby","checksum":"7cdcb97027866f7a81c490c6d15ada7f39666b5f6375f0821b7e97e0483b112f"}, {"name":"proc_to_ast","version":"0.1.0","platform":"ruby","checksum":"92a73fa66e2250a83f8589f818b0751bcf227c68f85916202df7af85082f8691"}, -{"name":"prometheus-client-mmap","version":"0.16.2","platform":"ruby","checksum":"36e7e96fdd603c2d1fed050ec71504797f3f8b2560123306ba72018ee3561165"}, +{"name":"prometheus-client-mmap","version":"0.17.0","platform":"ruby","checksum":"766d3706f7b26fed5a177843ab15b5b0dc108f9677d8bdbe0c4b5d9375c2af24"}, {"name":"pry","version":"0.13.1","platform":"java","checksum":"9612d825e2c3bc160633b2a4fae21041126ee33f1ac8035c851417e561b2b46c"}, {"name":"pry","version":"0.13.1","platform":"ruby","checksum":"1393918c415af46b6d09044d2b78dde92b29bc834fd85c369a950bab0826dc47"}, {"name":"pry-byebug","version":"3.9.0","platform":"ruby","checksum":"3bba08f97fea15b89cc299f3b5136e3b85763cd18cf84960eac4fbfbeb2ede24"}, diff --git a/Gemfile.lock b/Gemfile.lock index 56313bec18f..f12157122f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1082,7 +1082,7 @@ GEM coderay parser unparser - prometheus-client-mmap (0.16.2) + prometheus-client-mmap (0.17.0) pry (0.13.1) coderay (~> 1.1) method_source (~> 1.0) @@ -1768,7 +1768,7 @@ DEPENDENCIES pg_query (~> 2.2) png_quantizator (~> 0.2.1) premailer-rails (~> 1.10.3) - prometheus-client-mmap (~> 0.16) + prometheus-client-mmap (~> 0.17) pry-byebug pry-rails (~> 0.3.9) pry-shell (~> 0.5.1) diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json index f67519712cc..3b40970e62d 100644 --- a/app/assets/javascripts/editor/schema/ci.json +++ b/app/assets/javascripts/editor/schema/ci.json @@ -607,53 +607,65 @@ "secrets": { "type": "object", "markdownDescription": "Defines secrets to be injected as environment variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#secrets).", - "additionalProperties": { - "type": "object", - "description": "Environment variable name", - "properties": { - "vault": { - "oneOf": [ - { - "type": "string", - "description": "The secret to be fetched from Vault (e.g. 'production/db/password@ops' translates to secret 'ops/data/production/db', field `password`)" - }, - { - "type": "object", - "properties": { - "engine": { - "type": "object", - "properties": { - "name": { - "type": "string" + "patternProperties": { + ".*": { + "type": "object", + "properties": { + "vault": { + "oneOf": [ + { + "type": "string", + "markdownDescription": "The secret to be fetched from Vault (e.g. 'production/db/password@ops' translates to secret 'ops/data/production/db', field `password`). [Learn More](https://docs.gitlab.com/ee/ci/yaml/#secretsvault)" + }, + { + "type": "object", + "properties": { + "engine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "path": { + "type": "string" + } }, - "path": { - "type": "string" - } + "required": [ + "name", + "path" + ] }, - "required": [ - "name", - "path" - ] - }, - "path": { - "type": "string" + "path": { + "type": "string" + }, + "field": { + "type": "string" + } }, - "field": { - "type": "string" - } - }, - "required": [ - "engine", - "path", - "field" - ] - } - ] - } - }, - "required": [ - "vault" - ] + "required": [ + "engine", + "path", + "field" + ], + "additionalProperties": false + } + ] + }, + "file": { + "type": "boolean", + "default": true, + "markdownDescription": "Configures the secret to be stored as either a file or variable type CI/CD variable. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#secretsfile)" + }, + "token": { + "type": "string", + "description": "Specifies the JWT variable that should be used to authenticate with Hashicorp Vault." + } + }, + "required": [ + "vault" + ], + "additionalProperties": false + } } }, "before_script": { diff --git a/app/graphql/mutations/alert_management/alerts/set_assignees.rb b/app/graphql/mutations/alert_management/alerts/set_assignees.rb index c986111d290..500e2b868b1 100644 --- a/app/graphql/mutations/alert_management/alerts/set_assignees.rb +++ b/app/graphql/mutations/alert_management/alerts/set_assignees.rb @@ -20,7 +20,7 @@ module Mutations alert = authorized_find!(project_path: args[:project_path], iid: args[:iid]) result = set_assignees(alert, args[:assignee_usernames], args[:operation_mode]) - track_usage_event(:incident_management_alert_assigned, current_user.id) + track_alert_events('incident_management_alert_assigned', alert) prepare_response(result) end diff --git a/app/graphql/mutations/alert_management/alerts/todo/create.rb b/app/graphql/mutations/alert_management/alerts/todo/create.rb index 2a1056e8f64..999c0bec5af 100644 --- a/app/graphql/mutations/alert_management/alerts/todo/create.rb +++ b/app/graphql/mutations/alert_management/alerts/todo/create.rb @@ -11,7 +11,7 @@ module Mutations alert = authorized_find!(project_path: args[:project_path], iid: args[:iid]) result = ::AlertManagement::Alerts::Todo::CreateService.new(alert, current_user).execute - track_usage_event(:incident_management_alert_todo, current_user.id) + track_alert_events('incident_management_alert_todo', alert) prepare_response(result) end diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb index d01f200107c..2eef6bb9db7 100644 --- a/app/graphql/mutations/alert_management/base.rb +++ b/app/graphql/mutations/alert_management/base.rb @@ -39,6 +39,24 @@ module Mutations ::AlertManagement::AlertsFinder.new(current_user, project, args).execute.first end + + def track_alert_events(event, alert) + project = alert.project + namespace = project.namespace + track_usage_event(event, current_user.id) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase2, namespace) + + Gitlab::Tracking.event( + self.class.to_s, + event, + project: project, + namespace: namespace, + user: current_user, + label: 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly', + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context] + ) + end end end end diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb index 77a7d7a4147..7c8de6365e7 100644 --- a/app/graphql/mutations/alert_management/create_alert_issue.rb +++ b/app/graphql/mutations/alert_management/create_alert_issue.rb @@ -9,7 +9,7 @@ module Mutations alert = authorized_find!(project_path: args[:project_path], iid: args[:iid]) result = create_alert_issue(alert, current_user) - track_usage_event(:incident_management_incident_created, current_user.id) + track_alert_events('incident_management_incident_created', alert) track_usage_event(:incident_management_alert_create_incident, current_user.id) prepare_response(alert, result) diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb index 21566c7d66f..be271a7d795 100644 --- a/app/graphql/mutations/alert_management/update_alert_status.rb +++ b/app/graphql/mutations/alert_management/update_alert_status.rb @@ -13,7 +13,7 @@ module Mutations alert = authorized_find!(project_path: project_path, iid: iid) result = update_status(alert, status) - track_usage_event(:incident_management_alert_status_changed, current_user.id) + track_alert_events('incident_management_alert_status_changed', alert) prepare_response(result) end diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb index 56ad2418d19..07da54adde3 100644 --- a/app/graphql/types/ci/runner_type.rb +++ b/app/graphql/types/ci/runner_type.rb @@ -38,8 +38,8 @@ module Types field :executor_name, GraphQL::Types::String, null: true, description: 'Executor last advertised by the runner.', method: :executor_name - field :groups, ::Types::GroupType.connection_type, null: true, - description: 'Groups the runner is associated with. For group runners only.' + field :groups, 'Types::GroupConnection', null: true, + description: 'Groups the runner is associated with. For group runners only.' field :id, ::Types::GlobalIDType[::Ci::Runner], null: false, description: 'ID of the runner.' field :ip_address, GraphQL::Types::String, null: true, diff --git a/app/graphql/types/group_connection.rb b/app/graphql/types/group_connection.rb new file mode 100644 index 00000000000..e4332e24302 --- /dev/null +++ b/app/graphql/types/group_connection.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Normally this wouldn't be needed and we could use +# +# type Types::GroupType.connection_type, null: true +# +# in a resolver. However we can end up with cyclic definitions. +# Running the spec locally can result in errors like +# +# NameError: uninitialized constant Types::GroupType +# +# or other errors. To fix this, we created this file and use +# +# type "Types::GroupConnection", null: true +# +# which gives a delayed resolution, and the proper connection type. +# +# See gitlab/app/graphql/types/ci/runner_type.rb +# Reference: https://github.com/rmosolgo/graphql-ruby/issues/3974#issuecomment-1084444214 +# and https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#testing-tips-and-tricks +# +Types::GroupConnection = Types::GroupType.connection_type diff --git a/app/helpers/groups/observability_helper.rb b/app/helpers/groups/observability_helper.rb index a16e6ab13e3..26caac4ce7f 100644 --- a/app/helpers/groups/observability_helper.rb +++ b/app/helpers/groups/observability_helper.rb @@ -22,7 +22,7 @@ module Groups # When running Observability UI in standalone mode (i.e. not backed by Observability Backend) # the group-id is not required. This is mostly used for local dev - base_url = ENV['STANDALONE_OBSERVABILITY_UI'] == 'true' ? observability_url : "#{observability_url}/#{group.id}" + base_url = ENV['STANDALONE_OBSERVABILITY_UI'] == 'true' ? observability_url : "#{observability_url}/-/#{group.id}" sanitized_path = if params[:observability_path] && sanitize(params[:observability_path]) != '' CGI.unescapeHTML(sanitize(params[:observability_path])) diff --git a/app/models/users/group_callout.rb b/app/models/users/group_callout.rb index 3e3e424e9c9..2552407fa4c 100644 --- a/app/models/users/group_callout.rb +++ b/app/models/users/group_callout.rb @@ -23,7 +23,8 @@ module Users namespace_storage_limit_banner_alert_threshold: 12, # EE-only namespace_storage_limit_banner_error_threshold: 13, # EE-only usage_quota_trial_alert: 14, # EE-only - preview_usage_quota_free_plan_alert: 15 # EE-only + preview_usage_quota_free_plan_alert: 15, # EE-only + enforcement_at_limit_alert: 16 # EE-only } validates :group, presence: true diff --git a/app/services/concerns/incident_management/usage_data.rb b/app/services/concerns/incident_management/usage_data.rb index 27e60029ea3..40183085344 100644 --- a/app/services/concerns/incident_management/usage_data.rb +++ b/app/services/concerns/incident_management/usage_data.rb @@ -7,7 +7,23 @@ module IncidentManagement def track_incident_action(current_user, target, action) return unless target.incident? - track_usage_event(:"incident_management_#{action}", current_user.id) + event = "incident_management_#{action}" + track_usage_event(event, current_user.id) + + namespace = target.try(:namespace) + project = target.try(:project) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase2, target.try(:namespace)) + + Gitlab::Tracking.event( + self.class.to_s, + event, + project: project, + namespace: namespace, + user: current_user, + label: 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly', + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context] + ) end end end diff --git a/app/services/incident_management/timeline_events/base_service.rb b/app/services/incident_management/timeline_events/base_service.rb index 7168e2fdd38..1de382273de 100644 --- a/app/services/incident_management/timeline_events/base_service.rb +++ b/app/services/incident_management/timeline_events/base_service.rb @@ -24,6 +24,23 @@ module IncidentManagement def error_in_save(timeline_event) error(timeline_event.errors.full_messages.to_sentence) end + + def track_timeline_event(event, project) + namespace = project.namespace + track_usage_event(event, user.id) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase2, namespace) + + Gitlab::Tracking.event( + self.class.to_s, + event, + project: project, + namespace: namespace, + user: user, + label: 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly', + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context] + ) + end end end end diff --git a/app/services/incident_management/timeline_events/create_service.rb b/app/services/incident_management/timeline_events/create_service.rb index 71ff5b64515..3dd9bc172e2 100644 --- a/app/services/incident_management/timeline_events/create_service.rb +++ b/app/services/incident_management/timeline_events/create_service.rb @@ -106,7 +106,7 @@ module IncidentManagement create_timeline_event_tag_links(timeline_event, params[:timeline_event_tag_names]) - track_usage_event(:incident_management_timeline_event_created, user.id) + track_timeline_event("incident_management_timeline_event_created", project) success(timeline_event) else diff --git a/app/services/incident_management/timeline_events/destroy_service.rb b/app/services/incident_management/timeline_events/destroy_service.rb index e1c6bbbdb85..aba46cdda27 100644 --- a/app/services/incident_management/timeline_events/destroy_service.rb +++ b/app/services/incident_management/timeline_events/destroy_service.rb @@ -18,7 +18,7 @@ module IncidentManagement if timeline_event.destroy add_system_note(incident, user) - track_usage_event(:incident_management_timeline_event_deleted, user.id) + track_timeline_event('incident_management_timeline_event_deleted', project) success(timeline_event) else error_in_save(timeline_event) diff --git a/app/services/incident_management/timeline_events/update_service.rb b/app/services/incident_management/timeline_events/update_service.rb index 0e424f86e1a..dd67c6238c8 100644 --- a/app/services/incident_management/timeline_events/update_service.rb +++ b/app/services/incident_management/timeline_events/update_service.rb @@ -43,7 +43,7 @@ module IncidentManagement if timeline_event_saved add_system_note(timeline_event) - track_usage_event(:incident_management_timeline_event_edited, user.id) + track_timeline_event('incident_management_timeline_event_edited', timeline_event.project) success(timeline_event) else error_in_save(timeline_event) diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 28ea6b0ebf8..10407e99715 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -114,6 +114,11 @@ module Issues Milestones::IssuesCountService.new(milestone).delete_cache end + + override :allowed_create_params + def allowed_create_params(params) + super(params).except(:issue_type, :work_item_type_id, :work_item_type) + end end end diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index 0aed9e3ba40..71cc5581ae6 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -146,7 +146,7 @@ module Issues # don't enqueue immediately to prevent todos removal in case of a mistake TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, issue.id) if issue.confidential? create_confidentiality_note(issue) - track_usage_event(:incident_management_incident_change_confidential, current_user.id) + track_incident_action(current_user, issue, :incident_change_confidential) end end diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index 5b0ef44dad4..9ae31f8ac58 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -166,8 +166,9 @@ class TodoService # When user marks a target as todo def mark_todo(target, current_user) - attributes = attributes_for_todo(target.project, target, current_user, Todo::MARKED) - create_todos(current_user, attributes) + project = target.project + attributes = attributes_for_todo(project, target, current_user, Todo::MARKED) + create_todos(current_user, attributes, project&.namespace, project) end def todo_exist?(issuable, current_user) @@ -214,8 +215,9 @@ class TodoService end def create_request_review_todo(target, author, reviewers) - attributes = attributes_for_todo(target.project, target, author, Todo::REVIEW_REQUESTED) - create_todos(reviewers, attributes) + project = target.project + attributes = attributes_for_todo(project, target, author, Todo::REVIEW_REQUESTED) + create_todos(reviewers, attributes, project.namespace, project) end def create_member_access_request(member) @@ -225,12 +227,20 @@ class TodoService approvers = source.access_request_approvers_to_be_notified.map(&:user) return true if approvers.empty? - create_todos(approvers, attributes) + if source.instance_of? Project + project = source + namespace = project.namespace + else + project = nil + namespace = source + end + + create_todos(approvers, attributes, namespace, project) end private - def create_todos(users, attributes) + def create_todos(users, attributes, namespace, project) users = Array(users) return if users.empty? @@ -256,7 +266,7 @@ class TodoService todos = users.map do |user| issue_type = attributes.delete(:issue_type) - track_todo_creation(user, issue_type) + track_todo_creation(user, issue_type, namespace, project) Todo.create(attributes.merge(user_id: user.id)) end @@ -296,9 +306,10 @@ class TodoService def create_assignment_todo(target, author, old_assignees = []) if target.assignees.any? + project = target.project assignees = target.assignees - old_assignees - attributes = attributes_for_todo(target.project, target, author, Todo::ASSIGNED) - create_todos(assignees, attributes) + attributes = attributes_for_todo(project, target, author, Todo::ASSIGNED) + create_todos(assignees, attributes, project.namespace, project) end end @@ -313,22 +324,24 @@ class TodoService # Create Todos for directly addressed users directly_addressed_users = filter_directly_addressed_users(parent, note || target, author, skip_users) attributes = attributes_for_todo(parent, target, author, Todo::DIRECTLY_ADDRESSED, note) - create_todos(directly_addressed_users, attributes) + create_todos(directly_addressed_users, attributes, parent&.namespace, parent) # Create Todos for mentioned users mentioned_users = filter_mentioned_users(parent, note || target, author, skip_users + directly_addressed_users) attributes = attributes_for_todo(parent, target, author, Todo::MENTIONED, note) - create_todos(mentioned_users, attributes) + create_todos(mentioned_users, attributes, parent&.namespace, parent) end def create_build_failed_todo(merge_request, todo_author) - attributes = attributes_for_todo(merge_request.project, merge_request, todo_author, Todo::BUILD_FAILED) - create_todos(todo_author, attributes) + project = merge_request.project + attributes = attributes_for_todo(project, merge_request, todo_author, Todo::BUILD_FAILED) + create_todos(todo_author, attributes, project.namespace, project) end def create_unmergeable_todo(merge_request, todo_author) - attributes = attributes_for_todo(merge_request.project, merge_request, todo_author, Todo::UNMERGEABLE) - create_todos(todo_author, attributes) + project = merge_request.project + attributes = attributes_for_todo(project, merge_request, todo_author, Todo::UNMERGEABLE) + create_todos(todo_author, attributes, project.namespace, project) end def attributes_for_target(target) @@ -392,10 +405,23 @@ class TodoService PendingTodosFinder.new(users, criteria).execute end - def track_todo_creation(user, issue_type) + def track_todo_creation(user, issue_type, namespace, project) return unless issue_type == 'incident' - track_usage_event(:incident_management_incident_todo, user.id) + event = "incident_management_incident_todo" + track_usage_event(event, user.id) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase2, namespace) + + Gitlab::Tracking.event( + self.class.to_s, + event, + project: project, + namespace: namespace, + user: user, + label: 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly', + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context] + ) end def attributes_for_access_request_todos(source, author, action, note = nil) diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 89d25502c6b..bba5ef37051 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -1659,6 +1659,15 @@ :weight: 1 :idempotent: true :tags: [] +- :name: package_repositories:packages_debian_process_package_file + :worker_name: Packages::Debian::ProcessPackageFileWorker + :feature_category: :package_registry + :has_external_dependencies: false + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: true + :tags: [] - :name: package_repositories:packages_go_sync_packages :worker_name: Packages::Go::SyncPackagesWorker :feature_category: :package_registry diff --git a/app/workers/packages/debian/process_package_file_worker.rb b/app/workers/packages/debian/process_package_file_worker.rb new file mode 100644 index 00000000000..587c0b78c9c --- /dev/null +++ b/app/workers/packages/debian/process_package_file_worker.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module Packages + module Debian + class ProcessPackageFileWorker + include ApplicationWorker + include ::Packages::FIPS + include Gitlab::Utils::StrongMemoize + + data_consistency :always + + deduplicate :until_executed + idempotent! + + queue_namespace :package_repositories + feature_category :package_registry + + def perform(package_file_id, user_id, distribution_name, component_name) + raise DisabledError, 'Debian registry is not FIPS compliant' if Gitlab::FIPS.enabled? + + @package_file_id = package_file_id + @user_id = user_id + @distribution_name = distribution_name + @component_name = component_name + + return unless package_file && user && distribution_name && component_name + # return if file has already been processed + return unless package_file.debian_file_metadatum&.unknown? + + ::Packages::Debian::ProcessPackageFileService.new(package_file, user, distribution_name, component_name).execute + rescue StandardError => e + raise if e.instance_of?(DisabledError) + + Gitlab::ErrorTracking.log_exception(e, package_file_id: @package_file_id, user_id: @user_id, + distribution_name: @distribution_name, component_name: @component_name) + package_file.destroy! + end + + private + + def package_file + ::Packages::PackageFile.find_by_id(@package_file_id) + end + strong_memoize_attr :package_file + + def user + ::User.find_by_id(@user_id) + end + strong_memoize_attr :user + end + end +end diff --git a/config/events/1669814629_StatusPage__PublishService_incident_management_incident_published.yml b/config/events/1669814629_StatusPage__PublishService_incident_management_incident_published.yml new file mode 100644 index 00000000000..9e6f699786b --- /dev/null +++ b/config/events/1669814629_StatusPage__PublishService_incident_management_incident_published.yml @@ -0,0 +1,24 @@ +--- +description: Mirrored Service Ping Redis metric. Count of unique users that published incidents per month +category: StatusPage::PublishService +action: incident_management_incident_published +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ee +tiers: +- premium +- ultimate + diff --git a/config/events/1669815074_Mutations__AlertManagement__Alerts__Todo__Create_incident_management_alert_todo.yml b/config/events/1669815074_Mutations__AlertManagement__Alerts__Todo__Create_incident_management_alert_todo.yml new file mode 100644 index 00000000000..f94db886c51 --- /dev/null +++ b/config/events/1669815074_Mutations__AlertManagement__Alerts__Todo__Create_incident_management_alert_todo.yml @@ -0,0 +1,26 @@ +--- +description: Migrated Service Ping metric. Count of unique users adding alerts to the TODO list +category: Mutations::AlertManagement::Alerts::Todo::Create +action: incident_management_alert_todo +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223/diffs +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669817378_Mutations__AlertManagement__Alerts__SetAssignees_incident_management_alert_assigned.yml b/config/events/1669817378_Mutations__AlertManagement__Alerts__SetAssignees_incident_management_alert_assigned.yml new file mode 100644 index 00000000000..4b2c786149f --- /dev/null +++ b/config/events/1669817378_Mutations__AlertManagement__Alerts__SetAssignees_incident_management_alert_assigned.yml @@ -0,0 +1,26 @@ +--- +description: Count of unique users assigning an alert per week. Migrated form Service Ping metric +category: Mutations::AlertManagement::Alerts::SetAssignees +action: incident_management_alert_assigned +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669817630_Mutations__AlertManagement__CreateAlertIssue_incident_management_incident_created.yml b/config/events/1669817630_Mutations__AlertManagement__CreateAlertIssue_incident_management_incident_created.yml new file mode 100644 index 00000000000..28bd7ba89c6 --- /dev/null +++ b/config/events/1669817630_Mutations__AlertManagement__CreateAlertIssue_incident_management_incident_created.yml @@ -0,0 +1,26 @@ +--- +description: Migrated from Service Ping metric. Count of unique users creating incidents +category: Mutations::AlertManagement::CreateAlertIssue +action: incident_management_incident_created +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669817815_Mutations__AlertManagement__UpdateAlertStatus_incident_management_alert_status_change.yml b/config/events/1669817815_Mutations__AlertManagement__UpdateAlertStatus_incident_management_alert_status_change.yml new file mode 100644 index 00000000000..409d1186348 --- /dev/null +++ b/config/events/1669817815_Mutations__AlertManagement__UpdateAlertStatus_incident_management_alert_status_change.yml @@ -0,0 +1,26 @@ +--- +description: Count of unique users changing alert's status. Migrated from Service Ping metric +category: Mutations::AlertManagement::UpdateAlertStatus +action: incident_management_alert_status_changed +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669818009_IncidentManagement__TimelineEvents__CreateService_incident_management_timeline_event_.yml b/config/events/1669818009_IncidentManagement__TimelineEvents__CreateService_incident_management_timeline_event_.yml new file mode 100644 index 00000000000..b3033c4aa3b --- /dev/null +++ b/config/events/1669818009_IncidentManagement__TimelineEvents__CreateService_incident_management_timeline_event_.yml @@ -0,0 +1,27 @@ +--- +description: Count of unique users created timeline events +category: IncidentManagement::TimelineEvents::CreateService +action: incident_management_timeline_event_created +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: respond +product_category: incident_management +value_type: number +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669902189_IncidentManagement__TimelineEvents__DestroyService_incident_management_timeline_event.yml b/config/events/1669902189_IncidentManagement__TimelineEvents__DestroyService_incident_management_timeline_event.yml new file mode 100644 index 00000000000..a314f3c7b8e --- /dev/null +++ b/config/events/1669902189_IncidentManagement__TimelineEvents__DestroyService_incident_management_timeline_event.yml @@ -0,0 +1,26 @@ +--- +category: IncidentManagement::TimelineEvents::DestroyService +action: incident_management_timeline_event_deleted +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Event migrates from Service Ping metric. Count of unique users deleted timeline events" +product_section: ops +product_stage: monitor +product_group: respond +product_category: incident_management +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669902383_IncidentManagement__TimelineEvents__UpdateService_incident_management_timeline_event_.yml b/config/events/1669902383_IncidentManagement__TimelineEvents__UpdateService_incident_management_timeline_event_.yml new file mode 100644 index 00000000000..afab1a0f531 --- /dev/null +++ b/config/events/1669902383_IncidentManagement__TimelineEvents__UpdateService_incident_management_timeline_event_.yml @@ -0,0 +1,26 @@ +--- +category: IncidentManagement::TimelineEvents::UpdateService +action: incident_management_timeline_event_edited +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Event migrated form Service Ping metric. Count of unique users edited timeline events" +product_section: ops +product_stage: monitor +product_group: respond +product_category: incident_management +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669902538_IssueLinks__CreateService_incident_management_incident_relate.yml b/config/events/1669902538_IssueLinks__CreateService_incident_management_incident_relate.yml new file mode 100644 index 00000000000..00ac7581617 --- /dev/null +++ b/config/events/1669902538_IssueLinks__CreateService_incident_management_incident_relate.yml @@ -0,0 +1,26 @@ +--- +category: IssueLinks::CreateService +action: incident_management_incident_relate +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users adding issues per that are related to an incident. Migrated from Service Ping" +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669902705_IssueLinks__DestroyService_incident_management_incident_unrelate.yml b/config/events/1669902705_IssueLinks__DestroyService_incident_management_incident_unrelate.yml new file mode 100644 index 00000000000..4870e2b1f04 --- /dev/null +++ b/config/events/1669902705_IssueLinks__DestroyService_incident_management_incident_unrelate.yml @@ -0,0 +1,26 @@ +--- +category: IssueLinks::DestroyService +action: incident_management_incident_unrelate +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +milestone: "15.7" +description: "Count of unique users removing issue that are related to an incident. Migrated from Service Ping metric" +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669902889_Issues__CloseService_incident_management_incident_closed.yml b/config/events/1669902889_Issues__CloseService_incident_management_incident_closed.yml new file mode 100644 index 00000000000..8e6f54876b2 --- /dev/null +++ b/config/events/1669902889_Issues__CloseService_incident_management_incident_closed.yml @@ -0,0 +1,26 @@ +--- +category: Issues::CloseService +action: incident_management_incident_closed +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of users closing incidents. Migrated from Service Ping metric." +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669903092_Issues__ReopenService_incident_management_incident_reopened.yml b/config/events/1669903092_Issues__ReopenService_incident_management_incident_reopened.yml new file mode 100644 index 00000000000..33118e11051 --- /dev/null +++ b/config/events/1669903092_Issues__ReopenService_incident_management_incident_reopened.yml @@ -0,0 +1,26 @@ +--- +category: Issues::ReopenService +action: incident_management_incident_reopened +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users reopening incidents. Migrated from Service Ping metric." +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669903273_Issues__UpdateService_incident_management_incident_change_confidential.yml b/config/events/1669903273_Issues__UpdateService_incident_management_incident_change_confidential.yml new file mode 100644 index 00000000000..2992667da31 --- /dev/null +++ b/config/events/1669903273_Issues__UpdateService_incident_management_incident_change_confidential.yml @@ -0,0 +1,26 @@ +--- +category: Issues::UpdateService +action: incident_management_incident_change_confidential +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users changing incidents to confidential. Event migrated from Service Ping metric." +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669903414_Issues__ZoomLinkService_incident_management_incident_zoom_meeting.yml b/config/events/1669903414_Issues__ZoomLinkService_incident_management_incident_zoom_meeting.yml new file mode 100644 index 00000000000..5dc7506bc21 --- /dev/null +++ b/config/events/1669903414_Issues__ZoomLinkService_incident_management_incident_zoom_meeting.yml @@ -0,0 +1,26 @@ +--- +category: Issues::ZoomLinkService +action: incident_management_incident_zoom_meeting +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users creating Zoom meetings about incidents. Event migrated from Service Ping metric." +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669903530_Notes__CreateService_incident_management_incident_comment.yml b/config/events/1669903530_Notes__CreateService_incident_management_incident_comment.yml new file mode 100644 index 00000000000..f7b619e3277 --- /dev/null +++ b/config/events/1669903530_Notes__CreateService_incident_management_incident_comment.yml @@ -0,0 +1,26 @@ +--- +category: Notes::CreateService +action: incident_management_incident_comment +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users adding comments on incidents. Event migrated from Service Ping metric" +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1669903650_TodoService_incident_management_incident_todo.yml b/config/events/1669903650_TodoService_incident_management_incident_todo.yml new file mode 100644 index 00000000000..b8eee5ce23e --- /dev/null +++ b/config/events/1669903650_TodoService_incident_management_incident_todo.yml @@ -0,0 +1,26 @@ +--- +category: TodoService +action: incident_management_incident_todo +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +description: "Count of unique users adding incidents to the TODO list. Event migrated from Service Ping metric" +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/events/1670570965_Issues__UpdateService_incident_management_incident_assigned.yml b/config/events/1670570965_Issues__UpdateService_incident_management_incident_assigned.yml new file mode 100644 index 00000000000..22c1a41127b --- /dev/null +++ b/config/events/1670570965_Issues__UpdateService_incident_management_incident_assigned.yml @@ -0,0 +1,26 @@ +--- +description: Count of unique users assiging incidents per +category: Issues::UpdateService +action: incident_management_incident_assigned +label_description: "Mirrored Service Ping total metric key_path: redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly" +property_description: +value_description: +extra_properties: +identifiers: +- project +- user +- namespace +product_section: ops +product_stage: monitor +product_group: monitor +product_category: +milestone: "15.7" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105223 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/metrics/counts_28d/20221108101211_merge_request_authors_monthly.yml b/config/metrics/counts_28d/20221108101211_merge_request_authors_monthly.yml index 5987bde2d14..4e9d58bddad 100644 --- a/config/metrics/counts_28d/20221108101211_merge_request_authors_monthly.yml +++ b/config/metrics/counts_28d/20221108101211_merge_request_authors_monthly.yml @@ -6,9 +6,11 @@ product_stage: create product_group: code_review product_category: code_review value_type: number -status: active +status: removed milestone: "15.6" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/103334 +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106449 +milestone_removed: "15.7" time_frame: 28d data_source: database data_category: optional diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index e93aa09d28a..682a974fb4d 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -18772,6 +18772,7 @@ Represents a requirement. | <a id="requirementtitlehtml"></a>`titleHtml` | [`String`](#string) | GitLab Flavored Markdown rendering of `title`. | | <a id="requirementupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the requirement was last updated. | | <a id="requirementuserpermissions"></a>`userPermissions` | [`RequirementPermissions!`](#requirementpermissions) | Permissions for the current user on the resource. | +| <a id="requirementworkitemiid"></a>`workItemIid` | [`ID!`](#id) | Work item IID of the requirement, will replace current IID as identifier soon. | #### Fields with arguments diff --git a/doc/api/index.md b/doc/api/index.md index c75ccc0020b..ef054318c5c 100644 --- a/doc/api/index.md +++ b/doc/api/index.md @@ -26,12 +26,6 @@ Contributions are welcome. For an introduction and basic steps, see [How to make GitLab API calls](https://www.youtube.com/watch?v=0LsMC3ZiXkA). -## SCIM API **(PREMIUM SAAS)** - -GitLab provides a [SCIM API](scim.md) that both implements -[the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644) and provides the -`/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`. - ## GraphQL API A GraphQL API is available in GitLab. diff --git a/doc/api/scim.md b/doc/api/scim.md index 006af7a6eff..0ee9779ccbd 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -8,6 +8,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98354) in GitLab 15.5. +GitLab provides an SCIM API that both implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) +and provides the `/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`. + To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. diff --git a/doc/api/tags.md b/doc/api/tags.md index 35085baf93f..099448d5609 100644 --- a/doc/api/tags.md +++ b/doc/api/tags.md @@ -176,3 +176,56 @@ Parameters: | ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- | | `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | `tag_name` | string | yes | The name of a tag | + +## Get X.509 signature of a tag + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106578) in GitLab 15.7. + +Get the [X.509 signature from a tag](../user/project/repository/x509_signed_commits/index.md#sign-commits-and-tags-with-x509-certificates), +if it is signed. Unsigned tags return a `404 Not Found` response. + +```plaintext +GET /projects/:id/repository/tags/:tag_name/signature +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | +| `tag_name` | string | yes | The name of a tag. | + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository/tags/v1.1.1/signature" +``` + +Example response if tag is X.509 signed: + +```json +{ + "signature_type": "X509", + "verification_status": "unverified", + "x509_certificate": { + "id": 1, + "subject": "CN=gitlab@example.org,OU=Example,O=World", + "subject_key_identifier": "BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC", + "email": "gitlab@example.org", + "serial_number": 278969561018901340486471282831158785578, + "certificate_status": "good", + "x509_issuer": { + "id": 1, + "subject": "CN=PKI,OU=Example,O=World", + "subject_key_identifier": "AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB", + "crl_url": "http://example.com/pki.crl" + } + } +} +``` + +Example response if tag is unsigned: + +```json +{ + "message": "404 GPG Signature Not Found" +} +``` diff --git a/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md b/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md index 8485a36f7b0..a6efe68310e 100644 --- a/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md +++ b/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md @@ -1,6 +1,6 @@ --- status: proposed -creation-date: 2022-11-09 +creation-date: "2022-11-09" authors: [ "@ankitbhatnagar" ] coach: "@mappelman" approvers: [ "@sebastienpahl", "@nicholasklick" ] diff --git a/doc/user/group/access_and_permissions.md b/doc/user/group/access_and_permissions.md index 13a1fd31ee4..a7358db54df 100644 --- a/doc/user/group/access_and_permissions.md +++ b/doc/user/group/access_and_permissions.md @@ -228,7 +228,10 @@ projects in a group, allowing tighter control over project membership. For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md), you can guarantee that project membership cannot be modified during the audit. -You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group. +If group membership lock is enabled, the group owner can still: + +- Invite groups or add members to groups to give them access to projects in the **locked** group. +- Change the role of group members. The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group. @@ -239,8 +242,10 @@ To prevent members from being added to projects in a group: 1. Under **Membership**, select **Users cannot be added to projects in this group**. 1. Select **Save changes**. -All users who previously had permissions can no longer add members to a group. -API requests to add a new user to a project are not possible. +After you lock the membership for a group: + +- All users who previously had permissions can no longer add members to a group. +- API requests to add a new user to a project are not possible. ## Manage group memberships via LDAP **(PREMIUM SELF)** diff --git a/doc/user/markdown.md b/doc/user/markdown.md index d15268a938f..b5049dfb66d 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -1,6 +1,6 @@ --- -stage: Create -group: Source Code +stage: Plan +group: Project Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/user/search/img/basic_search_results_v15_1.png b/doc/user/search/img/basic_search_results_v15_1.png Binary files differdeleted file mode 100644 index 0de0b976d7d..00000000000 --- a/doc/user/search/img/basic_search_results_v15_1.png +++ /dev/null diff --git a/doc/user/search/img/basic_search_v15_1.png b/doc/user/search/img/basic_search_v15_1.png Binary files differdeleted file mode 100644 index 069d62ca80c..00000000000 --- a/doc/user/search/img/basic_search_v15_1.png +++ /dev/null diff --git a/doc/user/search/img/search_navbar_v15_7.png b/doc/user/search/img/search_navbar_v15_7.png Binary files differnew file mode 100644 index 00000000000..9175347b36f --- /dev/null +++ b/doc/user/search/img/search_navbar_v15_7.png diff --git a/doc/user/search/img/search_scope_v15_7.png b/doc/user/search/img/search_scope_v15_7.png Binary files differnew file mode 100644 index 00000000000..6395b5f1cda --- /dev/null +++ b/doc/user/search/img/search_scope_v15_7.png diff --git a/doc/user/search/index.md b/doc/user/search/index.md index 93797656a71..9536f7fe40a 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -53,12 +53,12 @@ Global search only flags with an error any search that includes more than: To start a search, type your search query in the search bar on the top-right of the screen. You must type at least two characters. - + After the results are displayed, you can modify the search, select a different type of data to search, or choose a specific group or project. - + ## Search in code diff --git a/lib/api/entities/tag_signature.rb b/lib/api/entities/tag_signature.rb new file mode 100644 index 00000000000..e75fd04109a --- /dev/null +++ b/lib/api/entities/tag_signature.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module API + module Entities + class TagSignature < Grape::Entity + expose :signature_type, documentation: { type: 'string', example: 'PGP' } + + expose :signature, merge: true do |tag| + ::API::Entities::X509Signature.represent tag.signature if tag.signature_type == :X509 + end + end + end +end diff --git a/lib/api/tags.rb b/lib/api/tags.rb index b412a17bc6f..4ddf22c726f 100644 --- a/lib/api/tags.rb +++ b/lib/api/tags.rb @@ -129,6 +129,24 @@ module API end end end + + desc "Get a tag's signature" do + success code: 200, model: Entities::TagSignature + tags %w[tags] + failure [ + { code: 404, message: 'Not found' } + ] + end + params do + requires :tag_name, type: String, desc: 'The name of the tag' + end + get ':id/repository/tags/:tag_name/signature', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :source_code_management do + tag = user_project.repository.find_tag(params[:tag_name]) + not_found! 'Tag' unless tag + not_found! 'Signature' unless tag.has_signature? + + present tag, with: Entities::TagSignature + end end end end diff --git a/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric.rb deleted file mode 100644 index a7f8bca8e08..00000000000 --- a/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Usage - module Metrics - module Instrumentations - class CountMergeRequestAuthorsMetric < DatabaseMetric - operation :distinct_count, column: :author_id - - relation { MergeRequest } - end - end - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index def7f2d018a..a0cfd270916 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -43034,6 +43034,11 @@ msgstr "" msgid "To import an SVN repository, check out %{svn_link}." msgstr "" +msgid "To invite more users, you can reduce the number of users in your namespace to %{free_limit} user or less. You can also upgrade to a paid tier which do not have user limits. If you need additional time, you can start a free 30-day trial which includes unlimited users." +msgid_plural "To invite more users, you can reduce the number of users in your namespace to %{free_limit} users or less. You can also upgrade to a paid tier which do not have user limits. If you need additional time, you can start a free 30-day trial which includes unlimited users." +msgstr[0] "" +msgstr[1] "" + msgid "To keep this project going, create a new issue" msgstr "" @@ -47997,6 +48002,9 @@ msgstr "" msgid "Your name" msgstr "" +msgid "Your namespace %{namespace_name} has reached the %{free_limit} user limit" +msgstr "" + msgid "Your namespace %{namespace_name} is over the %{free_limit} user limit and has been placed in a read-only state." msgstr "" diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh index fea77876b66..1481cecba74 100755 --- a/scripts/review_apps/review-apps.sh +++ b/scripts/review_apps/review-apps.sh @@ -373,7 +373,7 @@ function display_deployment_debug() { local namespace="${CI_ENVIRONMENT_SLUG}" # Install dig to inspect DNS entries - apt update && apt install dnsutils + apt update && apt install -y dnsutils echoinfo "[debugging data] Check review-app webservice DNS entry:" dig +short $(echo "${CI_ENVIRONMENT_URL}" | sed 's~http[s]*://~~g') diff --git a/spec/factories/work_items/work_item_types.rb b/spec/factories/work_items/work_item_types.rb index 1b6137503d3..d36cb6260c6 100644 --- a/spec/factories/work_items/work_item_types.rb +++ b/spec/factories/work_items/work_item_types.rb @@ -13,7 +13,7 @@ FactoryBot.define do # Expect base_types to exist on the DB if type_base_attributes.slice(:namespace, :namespace_id).compact.empty? - WorkItems::Type.find_or_initialize_by(type_base_attributes).tap { |type| type.assign_attributes(attributes) } + WorkItems::Type.find_or_initialize_by(type_base_attributes) else WorkItems::Type.new(attributes) end diff --git a/spec/frontend/editor/schema/ci/ci_schema_spec.js b/spec/frontend/editor/schema/ci/ci_schema_spec.js index b8b91eb8167..c822a0bfeaf 100644 --- a/spec/frontend/editor/schema/ci/ci_schema_spec.js +++ b/spec/frontend/editor/schema/ci/ci_schema_spec.js @@ -32,6 +32,7 @@ import VariablesYaml from './yaml_tests/positive_tests/variables.yml'; import JobWhenYaml from './yaml_tests/positive_tests/job_when.yml'; import IdTokensYaml from './yaml_tests/positive_tests/id_tokens.yml'; import HooksYaml from './yaml_tests/positive_tests/hooks.yml'; +import SecretsYaml from './yaml_tests/positive_tests/secrets.yml'; // YAML NEGATIVE TEST import ArtifactsNegativeYaml from './yaml_tests/negative_tests/artifacts.yml'; @@ -50,6 +51,7 @@ import VariablesInvalidSyntaxDescYaml from './yaml_tests/negative_tests/variable import VariablesWrongSyntaxUsageExpand from './yaml_tests/negative_tests/variables/wrong_syntax_usage_expand.yml'; import IdTokensNegativeYaml from './yaml_tests/negative_tests/id_tokens.yml'; import HooksNegative from './yaml_tests/negative_tests/hooks.yml'; +import SecretsNegativeYaml from './yaml_tests/negative_tests/secrets.yml'; const ajv = new Ajv({ strictTypes: false, @@ -87,6 +89,7 @@ describe('positive tests', () => { VariablesYaml, ProjectPathYaml, IdTokensYaml, + SecretsYaml, }), )('schema validates %s', (_, input) => { // We construct a new "JSON" from each main key that is inside a @@ -122,6 +125,7 @@ describe('negative tests', () => { ProjectPathIncludeLeadSlashYaml, ProjectPathIncludeNoSlashYaml, ProjectPathIncludeTailSlashYaml, + SecretsNegativeYaml, TriggerNegative, HooksNegative, }), diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/secrets.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/secrets.yml new file mode 100644 index 00000000000..14ba930b394 --- /dev/null +++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/secrets.yml @@ -0,0 +1,39 @@ +job_with_secrets_without_vault: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + token: $TEST_TOKEN + +job_with_secrets_with_extra_properties: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: test/db/password + extra_prop: TEST + +job_with_secrets_with_invalid_vault_property: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: + invalid: TEST + +job_with_secrets_with_missing_required_vault_property: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: + path: gitlab + +job_with_secrets_with_missing_required_engine_property: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: + engine: + path: kv diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/secrets.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/secrets.yml new file mode 100644 index 00000000000..083cb4348ed --- /dev/null +++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/secrets.yml @@ -0,0 +1,28 @@ +valid_job_with_secrets: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: test/db/password + +valid_job_with_secrets_and_token: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: test/db/password + token: $TEST_TOKEN + +valid_job_with_secrets_with_every_vault_keyword: + script: + - echo $TEST_DB_PASSWORD + secrets: + TEST_DB_PASSWORD: + vault: + engine: + name: test-engine + path: test + path: test/db + field: password + file: true + token: $TEST_TOKEN diff --git a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb index 31abbabe385..125e15b70cf 100644 --- a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb +++ b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb @@ -56,6 +56,15 @@ RSpec.describe Mutations::AlertManagement::Alerts::SetAssignees do context 'when operation mode is not specified' do it_behaves_like 'successful resolution' it_behaves_like 'an incident management tracked event', :incident_management_alert_assigned + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_alert_assigned' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end context 'when user does not have permission to update alerts' do diff --git a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb index ea5e21ec4b8..bcb7c74fa09 100644 --- a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb +++ b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb @@ -19,6 +19,15 @@ RSpec.describe Mutations::AlertManagement::Alerts::Todo::Create do it_behaves_like 'an incident management tracked event', :incident_management_alert_todo + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_alert_todo' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end + context 'when user does not have permissions' do let(:current_user) { nil } diff --git a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb index 4758ac526a5..e49596b37c9 100644 --- a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb +++ b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb @@ -30,6 +30,15 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do it_behaves_like 'an incident management tracked event', :incident_management_incident_created it_behaves_like 'an incident management tracked event', :incident_management_alert_create_incident + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_incident_created' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end context 'when CreateAlertIssue responds with an error' do @@ -46,6 +55,15 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do errors: ['An issue already exists'] ) end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_incident_created' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end end diff --git a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb index 2c2518e046a..22ad93df79b 100644 --- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb +++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb @@ -35,6 +35,15 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do let(:user) { current_user } end + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_alert_status_changed' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end + context 'error occurs when updating' do it 'returns the alert with errors' do # Stub an error on the alert diff --git a/spec/helpers/groups/observability_helper_spec.rb b/spec/helpers/groups/observability_helper_spec.rb index 4393f4e9bec..6d0a8631f78 100644 --- a/spec/helpers/groups/observability_helper_spec.rb +++ b/spec/helpers/groups/observability_helper_spec.rb @@ -10,17 +10,17 @@ RSpec.describe Groups::ObservabilityHelper do context 'if observability_path is missing from params' do it 'returns the iframe src for action: dashboards' do allow(helper).to receive(:params).and_return({ action: 'dashboards' }) - expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/#{group.id}/") + expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/-/#{group.id}/") end it 'returns the iframe src for action: manage' do allow(helper).to receive(:params).and_return({ action: 'manage' }) - expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/#{group.id}/dashboards") + expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/-/#{group.id}/dashboards") end it 'returns the iframe src for action: explore' do allow(helper).to receive(:params).and_return({ action: 'explore' }) - expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/#{group.id}/explore") + expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/-/#{group.id}/explore") end end @@ -28,7 +28,7 @@ RSpec.describe Groups::ObservabilityHelper do context 'if observability_path is valid' do it 'returns the iframe src by injecting the observability path' do allow(helper).to receive(:params).and_return({ action: '/explore', observability_path: '/foo?bar=foobar' }) - expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/#{group.id}/foo?bar=foobar") + expect(helper.observability_iframe_src(group)).to eq("#{observability_url}/-/#{group.id}/foo?bar=foobar") end end @@ -40,7 +40,7 @@ RSpec.describe Groups::ObservabilityHelper do "/test?groupId=<script>alert('attack!')</script>" }) expect(helper.observability_iframe_src(group)).to eq( - "#{observability_url}/#{group.id}/test?groupId=alert('attack!')" + "#{observability_url}/-/#{group.id}/test?groupId=alert('attack!')" ) end end diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb index af13c19c4aa..c087931d36a 100644 --- a/spec/lib/feature_spec.rb +++ b/spec/lib/feature_spec.rb @@ -162,6 +162,13 @@ RSpec.describe Feature, stub_feature_flags: false do stub_feature_flag_definition(:enabled_feature_flag, default_enabled: true) end + context 'when using redis cache', :use_clean_rails_redis_caching do + it 'does not make recursive feature-flag calls' do + expect(described_class).to receive(:enabled?).once.and_call_original + described_class.enabled?(:disabled_feature_flag) + end + end + context 'when self-recursive' do before do allow(Feature).to receive(:with_feature).and_wrap_original do |original, name, &block| diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric_spec.rb deleted file mode 100644 index 92459e92eac..00000000000 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountMergeRequestAuthorsMetric do - let(:expected_value) { 1 } - let(:start) { 30.days.ago.to_s(:db) } - let(:finish) { 2.days.ago.to_s(:db) } - - let(:expected_query) do - "SELECT COUNT(DISTINCT \"merge_requests\".\"author_id\") FROM \"merge_requests\"" \ - " WHERE \"merge_requests\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'" - end - - before do - user = create(:user) - user2 = create(:user) - - create(:merge_request, created_at: 1.year.ago, author: user) - create(:merge_request, created_at: 1.week.ago, author: user2) - create(:merge_request, created_at: 1.week.ago, author: user2) - end - - it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' } -end diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb index c71c2ae6c39..14cb18d04b8 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb @@ -632,7 +632,7 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do end context 'when unsupported widget input is sent' do - let_it_be(:test_case) { create(:work_item_type, :default, :test_case, name: 'some_test_case_name') } + let_it_be(:test_case) { create(:work_item_type, :default, :test_case) } let_it_be(:work_item) { create(:work_item, work_item_type: test_case, project: project) } let(:input) do @@ -642,7 +642,7 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do end it_behaves_like 'a mutation that returns top-level errors', - errors: ["Following widget keys are not supported by some_test_case_name type: [:hierarchy_widget]"] + errors: ["Following widget keys are not supported by Test Case type: [:hierarchy_widget]"] end end end diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb index 0ba0b718ad0..b02c7135b7b 100644 --- a/spec/requests/api/tags_spec.rb +++ b/spec/requests/api/tags_spec.rb @@ -479,4 +479,60 @@ RSpec.describe API::Tags, feature_category: :source_code_management do end end end + + describe 'GET /projects/:id/repository/tags/:tag_name/signature' do + let_it_be(:project) { create(:project, :repository, :public) } + let(:project_id) { project.id } + let(:route) { "/projects/#{project_id}/repository/tags/#{tag_name}/signature" } + + context 'when tag does not exist' do + let(:tag_name) { 'unknown' } + + it_behaves_like '404 response' do + let(:request) { get api(route, current_user) } + let(:message) { '404 Tag Not Found' } + end + end + + context 'unsigned tag' do + let(:tag_name) { 'v1.1.0' } + + it_behaves_like '404 response' do + let(:request) { get api(route, current_user) } + let(:message) { '404 Signature Not Found' } + end + end + + context 'x509 signed tag' do + let(:tag_name) { 'v1.1.1' } + let(:tag) { project.repository.find_tag(tag_name) } + let(:signature) { tag.signature } + let(:x509_certificate) { signature.x509_certificate } + let(:x509_issuer) { x509_certificate.x509_issuer } + + it 'returns correct JSON' do + get api(route, current_user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq( + 'signature_type' => 'X509', + 'verification_status' => signature.verification_status.to_s, + 'x509_certificate' => { + 'id' => x509_certificate.id, + 'subject' => x509_certificate.subject, + 'subject_key_identifier' => x509_certificate.subject_key_identifier, + 'email' => x509_certificate.email, + 'serial_number' => x509_certificate.serial_number, + 'certificate_status' => x509_certificate.certificate_status, + 'x509_issuer' => { + 'id' => x509_issuer.id, + 'subject' => x509_issuer.subject, + 'subject_key_identifier' => x509_issuer.subject_key_identifier, + 'crl_url' => x509_issuer.crl_url + } + } + ) + end + end + end end diff --git a/spec/requests/groups/observability_controller_spec.rb b/spec/requests/groups/observability_controller_spec.rb index 70ebe2d22e8..46690d60539 100644 --- a/spec/requests/groups/observability_controller_spec.rb +++ b/spec/requests/groups/observability_controller_spec.rb @@ -73,21 +73,21 @@ RSpec.describe Groups::ObservabilityController, feature_category: :tracing do describe 'GET #dashboards' do let(:path) { group_observability_dashboards_path(group) } - let(:expected_observability_path) { "#{observability_url}/#{group.id}/" } + let(:expected_observability_path) { "#{observability_url}/-/#{group.id}/" } it_behaves_like 'observability route request' end describe 'GET #manage' do let(:path) { group_observability_manage_path(group) } - let(:expected_observability_path) { "#{observability_url}/#{group.id}/dashboards" } + let(:expected_observability_path) { "#{observability_url}/-/#{group.id}/dashboards" } it_behaves_like 'observability route request' end describe 'GET #explore' do let(:path) { group_observability_explore_path(group) } - let(:expected_observability_path) { "#{observability_url}/#{group.id}/explore" } + let(:expected_observability_path) { "#{observability_url}/-/#{group.id}/explore" } it_behaves_like 'observability route request' end diff --git a/spec/services/incident_management/timeline_events/create_service_spec.rb b/spec/services/incident_management/timeline_events/create_service_spec.rb index b10862a78b5..a3810879c65 100644 --- a/spec/services/incident_management/timeline_events/create_service_spec.rb +++ b/spec/services/incident_management/timeline_events/create_service_spec.rb @@ -55,6 +55,15 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do end it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_created + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_timeline_event_created' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end subject(:execute) { service.execute } @@ -276,6 +285,15 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_created + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_timeline_event_created' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end + it 'successfully creates a database record', :aggregate_failures do expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1) end diff --git a/spec/services/incident_management/timeline_events/destroy_service_spec.rb b/spec/services/incident_management/timeline_events/destroy_service_spec.rb index e1b258960ae..f90ff72a2bf 100644 --- a/spec/services/incident_management/timeline_events/destroy_service_spec.rb +++ b/spec/services/incident_management/timeline_events/destroy_service_spec.rb @@ -65,6 +65,15 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do end it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_deleted + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:user) { current_user } + let(:action) { 'incident_management_timeline_event_deleted' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end end end diff --git a/spec/services/incident_management/timeline_events/update_service_spec.rb b/spec/services/incident_management/timeline_events/update_service_spec.rb index 8ccc6ded6d0..076ba059114 100644 --- a/spec/services/incident_management/timeline_events/update_service_spec.rb +++ b/spec/services/incident_management/timeline_events/update_service_spec.rb @@ -48,6 +48,14 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do end it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_edited + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace.reload } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_timeline_event_edited' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end shared_examples 'error response' do |message| diff --git a/spec/services/issue_links/create_service_spec.rb b/spec/services/issue_links/create_service_spec.rb index 9cb5980716a..88e8470658d 100644 --- a/spec/services/issue_links/create_service_spec.rb +++ b/spec/services/issue_links/create_service_spec.rb @@ -41,6 +41,14 @@ RSpec.describe IssueLinks::CreateService do it_behaves_like 'an incident management tracked event', :incident_management_incident_relate do let(:current_user) { user } end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_relate' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end end end diff --git a/spec/services/issue_links/destroy_service_spec.rb b/spec/services/issue_links/destroy_service_spec.rb index a478a2c1448..ecb53b5cd31 100644 --- a/spec/services/issue_links/destroy_service_spec.rb +++ b/spec/services/issue_links/destroy_service_spec.rb @@ -25,6 +25,14 @@ RSpec.describe IssueLinks::DestroyService do it_behaves_like 'an incident management tracked event', :incident_management_incident_unrelate do let(:current_user) { user } end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue_b.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_unrelate' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end end end diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index dcb17c95f3b..8e5717090b4 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -99,6 +99,14 @@ RSpec.describe Issues::CloseService do it_behaves_like 'an incident management tracked event', :incident_management_incident_closed + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_closed' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end + it 'creates a new escalation resolved escalation status', :aggregate_failures do expect { service.execute(issue) }.to change { IncidentManagement::IssuableEscalationStatus.where(issue: issue).count }.by(1) diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 7b51f9db8cd..7ab2046b6be 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -9,21 +9,22 @@ RSpec.describe Issues::CreateService do let_it_be_with_reload(:project) { create(:project, :public, group: group) } let_it_be(:user) { create(:user) } + let(:opts) { { title: 'title' } } let(:spam_params) { double } + let(:service) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params) } it_behaves_like 'rate limited service' do let(:key) { :issues_create } let(:key_scope) { %i[project current_user external_author] } let(:application_limit_key) { :issues_create_limit } let(:created_model) { Issue } - let(:service) { described_class.new(project: project, current_user: user, params: { title: 'title' }, spam_params: double) } end describe '#execute' do let_it_be(:assignee) { create(:user) } let_it_be(:milestone) { create(:milestone, project: project) } - let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute } + let(:result) { service.execute } let(:issue) { result[:issue] } before do @@ -54,6 +55,7 @@ RSpec.describe Issues::CreateService do let(:opts) do { title: 'Awesome issue', + issue_type: :task, description: 'please fix', assignee_ids: [assignee.id], label_ids: labels.map(&:id), @@ -118,10 +120,26 @@ RSpec.describe Issues::CreateService do expect(issue.labels).to match_array(labels) expect(issue.milestone).to eq(milestone) expect(issue.due_date).to eq(Date.tomorrow) - expect(issue.work_item_type.base_type).to eq('issue') + expect(issue.work_item_type.base_type).to eq('task') expect(issue.issue_customer_relations_contacts).to be_empty end + context 'when the work item type is not allowed to create' do + before do + allow_next_instance_of(::Issues::BuildService) do |instance| + allow(instance).to receive(:create_issue_type_allowed?).twice.and_return(false) + end + end + + it 'ignores the type and creates default issue' do + expect(result).to be_success + expect(issue).to be_persisted + expect(issue).to be_a(::Issue) + expect(issue.work_item_type.base_type).to eq('issue') + expect(issue.issue_type).to eq('issue') + end + end + it 'calls NewIssueWorker with correct arguments' do expect(NewIssueWorker).to receive(:perform_async).with(Integer, user.id, 'Issue') diff --git a/spec/services/issues/reopen_service_spec.rb b/spec/services/issues/reopen_service_spec.rb index 6013826f9b1..529b3ff266b 100644 --- a/spec/services/issues/reopen_service_spec.rb +++ b/spec/services/issues/reopen_service_spec.rb @@ -74,6 +74,14 @@ RSpec.describe Issues::ReopenService do it_behaves_like 'an incident management tracked event', :incident_management_incident_reopened + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_reopened' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end + it 'creates a timeline event' do expect(IncidentManagement::TimelineEvents::CreateService) .to receive(:reopen_incident) diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index f1ee62fd589..70fc6ffc38f 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -60,7 +60,7 @@ RSpec.describe Issues::UpdateService, :mailer do description: 'Also please fix', assignee_ids: [user2.id], state_event: 'close', - label_ids: [label.id], + label_ids: [label&.id], due_date: Date.tomorrow, discussion_locked: true, severity: 'low', @@ -189,6 +189,27 @@ RSpec.describe Issues::UpdateService, :mailer do subject { update_issue(confidential: true) } it_behaves_like 'an incident management tracked event', :incident_management_incident_change_confidential + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + let(:action) { 'incident_management_incident_change_confidential' } + let(:opts) do + { + title: 'New title', + description: 'Also please fix', + assignee_ids: [user2.id], + state_event: 'close', + due_date: Date.tomorrow, + discussion_locked: true, + severity: 'low', + milestone_id: milestone.id, + add_contacts: [contact.email] + } + end + end end end @@ -673,6 +694,14 @@ RSpec.describe Issues::UpdateService, :mailer do let(:current_user) { user } it_behaves_like 'an incident management tracked event', :incident_management_incident_assigned + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + let(:action) { "incident_management_incident_assigned" } + end end end diff --git a/spec/services/issues/zoom_link_service_spec.rb b/spec/services/issues/zoom_link_service_spec.rb index d662d9fa978..ad1f91ab5e6 100644 --- a/spec/services/issues/zoom_link_service_spec.rb +++ b/spec/services/issues/zoom_link_service_spec.rb @@ -95,6 +95,14 @@ RSpec.describe Issues::ZoomLinkService do let(:current_user) { user } it_behaves_like 'an incident management tracked event', :incident_management_incident_zoom_meeting + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_zoom_meeting' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end context 'with insufficient issue update permissions' do diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 4922e72b7a4..2f1c5a5b0f3 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -102,6 +102,14 @@ RSpec.describe Notes::CreateService do it_behaves_like 'an incident management tracked event', :incident_management_incident_comment do let(:current_user) { user } end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { issue.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_comment' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + end end describe 'event tracking', :snowplow do diff --git a/spec/services/packages/debian/process_package_file_service_spec.rb b/spec/services/packages/debian/process_package_file_service_spec.rb index f3d6cdee7b4..571861f42cf 100644 --- a/spec/services/packages/debian/process_package_file_service_spec.rb +++ b/spec/services/packages/debian/process_package_file_service_spec.rb @@ -109,7 +109,8 @@ RSpec.describe Packages::Debian::ProcessPackageFileService do end context 'with already processed package file' do - let!(:package_file) { create(:debian_package_file) } + let_it_be(:package_file) { create(:debian_package_file) } + let(:component_name) { 'main' } it 'raise ArgumentError', :aggregate_failures do diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index 56440d7b5f5..c4ed34a693e 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -209,6 +209,15 @@ RSpec.describe TodoService do it_behaves_like 'an incident management tracked event', :incident_management_incident_todo do let(:current_user) { john_doe } end + + it_behaves_like 'Snowplow event tracking with RedisHLL context' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:namespace) { project.namespace } + let(:category) { described_class.to_s } + let(:action) { 'incident_management_incident_todo' } + let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' } + let(:user) { john_doe } + end end end @@ -1251,6 +1260,19 @@ RSpec.describe TodoService do end describe '#create_member_access_request' do + context 'snowplow event tracking' do + it 'does not track snowplow event when todos are for access request for project', :snowplow do + user = create(:user) + project = create(:project) + requester = create(:project_member, project: project, user: assignee) + project.add_owner(user) + + expect_no_snowplow_event + + service.create_member_access_request(requester) + end + end + context 'when the group has more than 10 owners' do it 'creates todos for 10 recently active group owners' do group = create(:group, :public) diff --git a/spec/workers/packages/debian/process_package_file_worker_spec.rb b/spec/workers/packages/debian/process_package_file_worker_spec.rb new file mode 100644 index 00000000000..532bfb096a3 --- /dev/null +++ b/spec/workers/packages/debian/process_package_file_worker_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Debian::ProcessPackageFileWorker, type: :worker, feature_category: :package_registry do + let_it_be(:user) { create(:user) } + let_it_be_with_reload(:distribution) { create(:debian_project_distribution, :with_file, codename: 'unstable') } + + let(:incoming) { create(:debian_incoming, project: distribution.project) } + let(:distribution_name) { distribution.codename } + let(:worker) { described_class.new } + + describe '#perform' do + let(:package_file_id) { package_file.id } + let(:user_id) { user.id } + + subject { worker.perform(package_file_id, user_id, distribution_name, component_name) } + + shared_examples 'returns early without error' do + it 'returns early without error' do + expect(Gitlab::ErrorTracking).not_to receive(:log_exception) + expect(::Packages::Debian::ProcessPackageFileService).not_to receive(:new) + + subject + end + end + + using RSpec::Parameterized::TableSyntax + + where(:case_name, :expected_file_type, :file_name, :component_name) do + 'with a deb' | 'deb' | 'libsample0_1.2.3~alpha2_amd64.deb' | 'main' + 'with an udeb' | 'udeb' | 'sample-udeb_1.2.3~alpha2_amd64.udeb' | 'contrib' + end + + with_them do + context 'with Debian package file' do + let(:package_file) { incoming.package_files.with_file_name(file_name).first } + + context 'with mocked service' do + it 'calls ProcessPackageFileService' do + expect(Gitlab::ErrorTracking).not_to receive(:log_exception) + expect_next_instance_of(::Packages::Debian::ProcessPackageFileService) do |service| + expect(service).to receive(:execute) + .with(no_args) + end + + subject + end + end + + context 'with non existing user' do + let(:user_id) { non_existing_record_id } + + it_behaves_like 'returns early without error' + end + + context 'with nil user id' do + let(:user_id) { nil } + + it_behaves_like 'returns early without error' + end + + context 'when the service raises an error' do + let(:package_file) { incoming.package_files.with_file_name('sample_1.2.3~alpha2.tar.xz').first } + + it 'removes package file', :aggregate_failures do + expect(Gitlab::ErrorTracking).to receive(:log_exception).with( + instance_of(ArgumentError), + package_file_id: package_file_id, + user_id: user_id, + distribution_name: distribution_name, + component_name: component_name + ) + expect { subject } + .to not_change(Packages::Package, :count) + .and change { Packages::PackageFile.count }.by(-1) + .and change { incoming.package_files.count }.from(7).to(6) + + expect { package_file.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { [package_file.id, user.id, distribution_name, component_name] } + + it 'sets the Debian file type as deb', :aggregate_failures do + expect(Gitlab::ErrorTracking).not_to receive(:log_exception) + + # Using subject inside this block will process the job multiple times + expect { subject } + .to change { Packages::Package.count }.from(1).to(2) + .and not_change(Packages::PackageFile, :count) + .and change { incoming.package_files.count }.from(7).to(6) + .and change { + package_file&.debian_file_metadatum&.reload&.file_type + }.from('unknown').to(expected_file_type) + + created_package = Packages::Package.last + expect(created_package.name).to eq 'sample' + expect(created_package.version).to eq '1.2.3~alpha2' + expect(created_package.creator).to eq user + end + end + end + end + + context 'with already processed package file' do + let_it_be(:package_file) { create(:debian_package_file) } + + let(:component_name) { 'main' } + + it_behaves_like 'returns early without error' + end + + context 'with a deb' do + let(:package_file) { incoming.package_files.with_file_name('libsample0_1.2.3~alpha2_amd64.deb').first } + let(:component_name) { 'main' } + + context 'with FIPS mode enabled', :fips_mode do + it 'raises an error' do + expect { subject }.to raise_error(::Packages::FIPS::DisabledError) + end + end + + context 'with non existing package file' do + let(:package_file_id) { non_existing_record_id } + + it_behaves_like 'returns early without error' + end + + context 'with nil package file id' do + let(:package_file_id) { nil } + + it_behaves_like 'returns early without error' + end + end + end +end diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go index 7b9ac6b996e..ad9623f569c 100644 --- a/workhorse/internal/upload/rewrite.go +++ b/workhorse/internal/upload/rewrite.go @@ -67,11 +67,8 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, fi // Create multipart reader reader, err := r.MultipartReader() if err != nil { - if err == http.ErrNotMultipart { - // We want to be able to recognize http.ErrNotMultipart elsewhere so no fmt.Errorf - return http.ErrNotMultipart - } - return fmt.Errorf("get multipart reader: %v", err) + // We want to be able to recognize these errors elsewhere so no fmt.Errorf + return err } multipartUploadRequests.WithLabelValues(filter.Name()).Inc() diff --git a/workhorse/internal/upload/uploads.go b/workhorse/internal/upload/uploads.go index f214e1ac297..32e51fea9e5 100644 --- a/workhorse/internal/upload/uploads.go +++ b/workhorse/internal/upload/uploads.go @@ -51,7 +51,7 @@ func interceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Hand err := rewriteFormFilesFromMultipart(r, writer, filter, fa, p) if err != nil { switch err { - case ErrInjectedClientParam: + case ErrInjectedClientParam, http.ErrMissingBoundary: helper.CaptureAndFail(w, r, err, "Bad Request", http.StatusBadRequest) case ErrTooManyFilesUploaded: helper.CaptureAndFail(w, r, err, err.Error(), http.StatusBadRequest) diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go index 3655e9fc8c9..cc786079e36 100644 --- a/workhorse/internal/upload/uploads_test.go +++ b/workhorse/internal/upload/uploads_test.go @@ -352,6 +352,18 @@ func TestInvalidFileNames(t *testing.T) { } } +func TestBadMultipartHeader(t *testing.T) { + httpRequest, err := http.NewRequest("POST", "/example", bytes.NewReader(nil)) + require.NoError(t, err) + + // Invalid header: missing boundary + httpRequest.Header.Set("Content-Type", "multipart/form-data") + + response := httptest.NewRecorder() + testInterceptMultipartFiles(t, response, httpRequest, nilHandler, &SavedFileTracker{Request: httpRequest}) + require.Equal(t, 400, response.Code) +} + func TestContentDispositionRewrite(t *testing.T) { testhelper.ConfigureSecret() |
