summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-12-13 12:09:26 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-13 12:09:26 +0000
commit9fdb3dbd6bacb125d40290aac8409da2f9fe19fc (patch)
tree532a0cfc06fa0f4c1d718a33804e6bbf2b650e70
parent2d8c28f1d32709280506507f3b6e6d2da7440da9 (diff)
downloadgitlab-ce-9fdb3dbd6bacb125d40290aac8409da2f9fe19fc.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop.yml1
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/editor/schema/ci.json100
-rw-r--r--app/graphql/mutations/alert_management/alerts/set_assignees.rb2
-rw-r--r--app/graphql/mutations/alert_management/alerts/todo/create.rb2
-rw-r--r--app/graphql/mutations/alert_management/base.rb18
-rw-r--r--app/graphql/mutations/alert_management/create_alert_issue.rb2
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb2
-rw-r--r--app/graphql/types/ci/runner_type.rb4
-rw-r--r--app/graphql/types/group_connection.rb22
-rw-r--r--app/helpers/groups/observability_helper.rb2
-rw-r--r--app/models/users/group_callout.rb3
-rw-r--r--app/services/concerns/incident_management/usage_data.rb18
-rw-r--r--app/services/incident_management/timeline_events/base_service.rb17
-rw-r--r--app/services/incident_management/timeline_events/create_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/destroy_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/update_service.rb2
-rw-r--r--app/services/issues/base_service.rb5
-rw-r--r--app/services/issues/update_service.rb2
-rw-r--r--app/services/todo_service.rb60
-rw-r--r--app/workers/all_queues.yml9
-rw-r--r--app/workers/packages/debian/process_package_file_worker.rb52
-rw-r--r--config/events/1669814629_StatusPage__PublishService_incident_management_incident_published.yml24
-rw-r--r--config/events/1669815074_Mutations__AlertManagement__Alerts__Todo__Create_incident_management_alert_todo.yml26
-rw-r--r--config/events/1669817378_Mutations__AlertManagement__Alerts__SetAssignees_incident_management_alert_assigned.yml26
-rw-r--r--config/events/1669817630_Mutations__AlertManagement__CreateAlertIssue_incident_management_incident_created.yml26
-rw-r--r--config/events/1669817815_Mutations__AlertManagement__UpdateAlertStatus_incident_management_alert_status_change.yml26
-rw-r--r--config/events/1669818009_IncidentManagement__TimelineEvents__CreateService_incident_management_timeline_event_.yml27
-rw-r--r--config/events/1669902189_IncidentManagement__TimelineEvents__DestroyService_incident_management_timeline_event.yml26
-rw-r--r--config/events/1669902383_IncidentManagement__TimelineEvents__UpdateService_incident_management_timeline_event_.yml26
-rw-r--r--config/events/1669902538_IssueLinks__CreateService_incident_management_incident_relate.yml26
-rw-r--r--config/events/1669902705_IssueLinks__DestroyService_incident_management_incident_unrelate.yml26
-rw-r--r--config/events/1669902889_Issues__CloseService_incident_management_incident_closed.yml26
-rw-r--r--config/events/1669903092_Issues__ReopenService_incident_management_incident_reopened.yml26
-rw-r--r--config/events/1669903273_Issues__UpdateService_incident_management_incident_change_confidential.yml26
-rw-r--r--config/events/1669903414_Issues__ZoomLinkService_incident_management_incident_zoom_meeting.yml26
-rw-r--r--config/events/1669903530_Notes__CreateService_incident_management_incident_comment.yml26
-rw-r--r--config/events/1669903650_TodoService_incident_management_incident_todo.yml26
-rw-r--r--config/events/1670570965_Issues__UpdateService_incident_management_incident_assigned.yml26
-rw-r--r--config/metrics/counts_28d/20221108101211_merge_request_authors_monthly.yml4
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/api/index.md6
-rw-r--r--doc/api/scim.md3
-rw-r--r--doc/api/tags.md53
-rw-r--r--doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md2
-rw-r--r--doc/user/group/access_and_permissions.md11
-rw-r--r--doc/user/markdown.md4
-rw-r--r--doc/user/search/img/basic_search_results_v15_1.pngbin17833 -> 0 bytes
-rw-r--r--doc/user/search/img/basic_search_v15_1.pngbin10995 -> 0 bytes
-rw-r--r--doc/user/search/img/search_navbar_v15_7.pngbin0 -> 26983 bytes
-rw-r--r--doc/user/search/img/search_scope_v15_7.pngbin0 -> 287661 bytes
-rw-r--r--doc/user/search/index.md4
-rw-r--r--lib/api/entities/tag_signature.rb13
-rw-r--r--lib/api/tags.rb18
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric.rb15
-rw-r--r--locale/gitlab.pot8
-rwxr-xr-xscripts/review_apps/review-apps.sh2
-rw-r--r--spec/factories/work_items/work_item_types.rb2
-rw-r--r--spec/frontend/editor/schema/ci/ci_schema_spec.js4
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/secrets.yml39
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/secrets.yml28
-rw-r--r--spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb9
-rw-r--r--spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb9
-rw-r--r--spec/graphql/mutations/alert_management/create_alert_issue_spec.rb18
-rw-r--r--spec/graphql/mutations/alert_management/update_alert_status_spec.rb9
-rw-r--r--spec/helpers/groups/observability_helper_spec.rb10
-rw-r--r--spec/lib/feature_spec.rb7
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_merge_request_authors_metric_spec.rb25
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb4
-rw-r--r--spec/requests/api/tags_spec.rb56
-rw-r--r--spec/requests/groups/observability_controller_spec.rb6
-rw-r--r--spec/services/incident_management/timeline_events/create_service_spec.rb18
-rw-r--r--spec/services/incident_management/timeline_events/destroy_service_spec.rb9
-rw-r--r--spec/services/incident_management/timeline_events/update_service_spec.rb8
-rw-r--r--spec/services/issue_links/create_service_spec.rb8
-rw-r--r--spec/services/issue_links/destroy_service_spec.rb8
-rw-r--r--spec/services/issues/close_service_spec.rb8
-rw-r--r--spec/services/issues/create_service_spec.rb24
-rw-r--r--spec/services/issues/reopen_service_spec.rb8
-rw-r--r--spec/services/issues/update_service_spec.rb31
-rw-r--r--spec/services/issues/zoom_link_service_spec.rb8
-rw-r--r--spec/services/notes/create_service_spec.rb8
-rw-r--r--spec/services/packages/debian/process_package_file_service_spec.rb3
-rw-r--r--spec/services/todo_service_spec.rb22
-rw-r--r--spec/workers/packages/debian/process_package_file_worker_spec.rb138
-rw-r--r--workhorse/internal/upload/rewrite.go7
-rw-r--r--workhorse/internal/upload/uploads.go2
-rw-r--r--workhorse/internal/upload/uploads_test.go12
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
diff --git a/Gemfile b/Gemfile
index 9d88b56426b..03b06c63fa2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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
deleted file mode 100644
index 0de0b976d7d..00000000000
--- a/doc/user/search/img/basic_search_results_v15_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/basic_search_v15_1.png b/doc/user/search/img/basic_search_v15_1.png
deleted file mode 100644
index 069d62ca80c..00000000000
--- a/doc/user/search/img/basic_search_v15_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/search_navbar_v15_7.png b/doc/user/search/img/search_navbar_v15_7.png
new file mode 100644
index 00000000000..9175347b36f
--- /dev/null
+++ b/doc/user/search/img/search_navbar_v15_7.png
Binary files differ
diff --git a/doc/user/search/img/search_scope_v15_7.png b/doc/user/search/img/search_scope_v15_7.png
new file mode 100644
index 00000000000..6395b5f1cda
--- /dev/null
+++ b/doc/user/search/img/search_scope_v15_7.png
Binary files differ
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.
-![basic search](img/basic_search_v15_1.png)
+![search navbar](img/search_navbar_v15_7.png)
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.
-![basic search results](img/basic_search_results_v15_1.png)
+![search scope](img/search_scope_v15_7.png)
## 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()