summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-18 03:09:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-18 03:09:28 +0000
commit37ea4b5fbf55e039a2255f0f5d5508e5f479775c (patch)
treed64f686008ae7ef96f6ffd3cd498880022af581a
parentcf9694dd845a10c40449f2cfa539af1836f5c6e9 (diff)
downloadgitlab-ce-37ea4b5fbf55e039a2255f0f5d5508e5f479775c.tar.gz
Add latest changes from gitlab-org/gitlab@master
-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/create_alert_issue.rb2
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb2
-rw-r--r--app/helpers/projects_helper.rb2
-rw-r--r--app/models/design_management/design_collection.rb60
-rw-r--r--app/services/ci/create_job_artifacts_service.rb2
-rw-r--r--app/services/concerns/incident_management/usage_data.rb2
-rw-r--r--app/services/issues/update_service.rb2
-rw-r--r--app/services/notes/create_service.rb2
-rw-r--r--app/services/todo_service.rb2
-rw-r--r--app/views/projects/forks/error.html.haml30
-rw-r--r--changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml5
-rw-r--r--doc/development/telemetry/usage_ping.md35
-rw-r--r--doc/user/project/canary_deployments.md6
-rw-r--r--lib/gitlab/utils/usage_data.rb8
-rw-r--r--spec/features/invites_spec.rb2
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb46
-rw-r--r--spec/models/design_management/design_collection_spec.rb58
19 files changed, 238 insertions, 32 deletions
diff --git a/app/graphql/mutations/alert_management/alerts/set_assignees.rb b/app/graphql/mutations/alert_management/alerts/set_assignees.rb
index d755b670726..517c20a85d0 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)
+ track_usage_event(:incident_management_alert_assigned, current_user.id)
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 0a7126c2e5a..2a1056e8f64 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)
+ track_usage_event(:incident_management_alert_todo, current_user.id)
prepare_response(result)
end
diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb
index 3ca2189d1a0..2ddb94700c2 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)
+ track_usage_event(:incident_management_incident_created, current_user.id)
prepare_response(alert, result)
end
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
index 47389c2d678..1e14bae048a 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: args[:project_path], iid: args[:iid])
result = update_status(alert, args[:status])
- track_usage_event(:incident_management_alert_status_changed, current_user)
+ track_usage_event(:incident_management_alert_status_changed, current_user.id)
prepare_response(result)
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 9d72e1d0d6e..72cc07b13a5 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -7,7 +7,7 @@ module ProjectsHelper
end
def link_to_project(project)
- link_to namespace_project_path(namespace_id: project.namespace, id: project), title: h(project.name) do
+ link_to namespace_project_path(namespace_id: project.namespace, id: project), title: h(project.name), class: 'gl-link' do
title = content_tag(:span, project.name, class: 'project-name')
if project.namespace
diff --git a/app/models/design_management/design_collection.rb b/app/models/design_management/design_collection.rb
index 96d5f4c2419..c48b36588c9 100644
--- a/app/models/design_management/design_collection.rb
+++ b/app/models/design_management/design_collection.rb
@@ -6,8 +6,34 @@ module DesignManagement
delegate :designs, :project, to: :issue
+ state_machine :copy_state, initial: :ready, namespace: :copy do
+ after_transition any => any, do: :update_stored_copy_state!
+
+ event :start do
+ transition ready: :in_progress
+ end
+
+ event :end do
+ transition in_progress: :ready
+ end
+
+ event :error do
+ transition in_progress: :error
+ end
+
+ event :reset do
+ transition any => :ready
+ end
+ end
+
def initialize(issue)
+ super() # Necessary to initialize state_machine
+
@issue = issue
+
+ if stored_copy_state = get_stored_copy_state
+ @copy_state = stored_copy_state
+ end
end
def ==(other)
@@ -30,5 +56,39 @@ module DesignManagement
def designs_by_filename(filenames)
designs.current.where(filename: filenames)
end
+
+ private
+
+ def update_stored_copy_state!
+ # As "ready" is the initial copy state we can clear the cached value
+ # rather than persist it.
+ if copy_ready?
+ unset_store_copy_state!
+ else
+ set_stored_copy_state!
+ end
+ end
+
+ def copy_state_cache_key
+ "DesignCollection/copy_state/issue=#{issue.id}"
+ end
+
+ def get_stored_copy_state
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(copy_state_cache_key)
+ end
+ end
+
+ def set_stored_copy_state!
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(copy_state_cache_key, copy_state)
+ end
+ end
+
+ def unset_store_copy_state!
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.del(copy_state_cache_key)
+ end
+ end
end
end
diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb
index 81586332f51..1fe65898d55 100644
--- a/app/services/ci/create_job_artifacts_service.rb
+++ b/app/services/ci/create_job_artifacts_service.rb
@@ -27,7 +27,7 @@ module Ci
if lsif?(artifact_type)
headers[:ProcessLsif] = true
- track_usage_event('i_source_code_code_intelligence', project)
+ track_usage_event('i_source_code_code_intelligence', project.id)
end
success(headers: headers)
diff --git a/app/services/concerns/incident_management/usage_data.rb b/app/services/concerns/incident_management/usage_data.rb
index b625c519edc..b91aa59099d 100644
--- a/app/services/concerns/incident_management/usage_data.rb
+++ b/app/services/concerns/incident_management/usage_data.rb
@@ -7,7 +7,7 @@ module IncidentManagement
def track_incident_action(current_user, target, action)
return unless target.incident?
- track_usage_event(:"incident_management_#{action}", current_user)
+ track_usage_event(:"incident_management_#{action}", current_user.id)
end
# No-op as optionally overridden in implementing classes.
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index bff8501d7d4..ce21b2e0275 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -52,7 +52,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)
+ track_usage_event(:incident_management_incident_change_confidential, current_user.id)
end
added_labels = issue.labels - old_labels
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 446d884be47..e26f662a697 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -111,7 +111,7 @@ module Notes
def track_event(note, user)
return unless note.noteable.is_a?(Issue) && note.noteable.incident?
- track_usage_event(:incident_management_incident_comment, user)
+ track_usage_event(:incident_management_incident_comment, user.id)
end
end
end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 3157dd5a5fe..0eb099753cb 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -356,7 +356,7 @@ class TodoService
def track_todo_creation(user, issue_type)
return unless issue_type == 'incident'
- track_usage_event(:incident_management_incident_todo, user)
+ track_usage_event(:incident_management_incident_todo, user.id)
end
end
diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml
index 5d527f1bcfb..0c15796b667 100644
--- a/app/views/projects/forks/error.html.haml
+++ b/app/views/projects/forks/error.html.haml
@@ -1,20 +1,22 @@
- page_title _("Fork project")
- if @forked_project && !@forked_project.saved?
- .alert.alert-danger.alert-block
- %h4
+ .gl-alert.gl-alert-danger.gl-mt-5
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon')
+ %h4.gl-alert-title
= sprite_icon('fork')
= _("Fork Error!")
- %p
- = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
-
- - if @forked_project && @forked_project.errors.any?
+ .gl-alert-body
%p
- &ndash;
- - error = @forked_project.errors.full_messages.first
- - if error.include?("already been taken")
- = _("Name has already been taken")
- - else
- = error
+ = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
+
+ - if @forked_project && @forked_project.errors.any?
+ %p
+ &ndash;
+ - error = @forked_project.errors.full_messages.first
+ - if error.include?("already been taken")
+ = _("Name has already been taken")
+ - else
+ = error
- %p
- = link_to _("Try to fork again"), new_project_fork_path(@project), title: _("Fork"), class: "btn"
+ .gl-alert-actions
+ = link_to _("Try to fork again"), new_project_fork_path(@project), title: _("Fork"), class: "btn gl-alert-action btn-info btn-md gl-button"
diff --git a/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml b/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml
new file mode 100644
index 00000000000..e9ed91a58ab
--- /dev/null
+++ b/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/forks/error.html.haml
+merge_request: 41292
+author: Gilang Gumilar
+type: changed
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
index 2314661e511..ff4e7e0797b 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -327,6 +327,20 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
end
```
+1. Track event using `track_usage_event(event_name, values) in services and graphql
+
+ Increment unique values count using Redis HLL, for given event name.
+
+ Example:
+
+ [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/issues/update_service.rb)
+
+ [Track usage event for incident created in graphql](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb)
+
+ ```ruby
+ track_usage_event(:incident_management_incident_created, current_user.id)
+ ```
+
1. Track event using `UsageData` API
Increment unique users count using Redis HLL, for given event name.
@@ -850,3 +864,24 @@ The following is example content of the Usage Ping payload.
}
}
```
+
+## Exporting Usage Ping SQL queries and definitions
+
+Two Rake tasks exist to export Usage Ping definitions.
+
+- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`.
+- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`.
+- The Rake tasks calculate the `alt_usage_data` metrics.
+
+In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively:
+
+```shell
+# for YAML export
+bin/rake gitlab:usage_data:dump_sql_in_yaml
+
+# for JSON export
+bin/rake gitlab:usage_data:dump_sql_in_json
+
+# You may pipe the output into a file
+bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
+```
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index 852baf1f628..afce3869cbf 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -48,9 +48,9 @@ Canary deployments require that you properly configure Deploy Boards:
template for canary deployments that GitLab provides.
Depending on the deploy, the label should be either `stable` or `canary`.
-Usually, `stable` and blank or missing label means the same thing, and `canary`
-or any other track means canary/temporary.
-This allows GitLab to discover whether deployment is stable or canary (temporary).
+GitLab assumes the track label is `stable` if the label is blank or missing.
+Any other track label is considered `canary` (temporary).
+This allows GitLab to discover whether a deployment is stable or canary (temporary).
Once all of the above are set up and the pipeline has run at least once,
navigate to the environments page under **Pipelines > Environments**.
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 3c998987427..ca6a36c9cea 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -102,11 +102,13 @@ module Gitlab
yield.merge(key => Time.current)
end
- def track_usage_event(metric_name, target)
- return unless Feature.enabled?(:"usage_data_#{metric_name}", default_enabled: true)
+ # @param event_name [String] the event name
+ # @param values [Array|String] the values counted
+ def track_usage_event(event_name, values)
+ return unless Feature.enabled?(:"usage_data_#{event_name}", default_enabled: true)
return unless Gitlab::CurrentSettings.usage_ping_enabled?
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(target.id, metric_name.to_s)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name.to_s)
end
private
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 26b9b398692..3954de56eea 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Invites', :aggregate_failures do
+RSpec.describe 'Group or Project invitations', :aggregate_failures do
let(:user) { create(:user, email: 'user@example.com') }
let(:owner) { create(:user, name: 'John Doe') }
let(:group) { create(:group, name: 'Owned') }
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index bafd5cc199e..362cbaa78e9 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -209,4 +209,50 @@ RSpec.describe Gitlab::Utils::UsageData do
end
end
end
+
+ describe '#track_usage_event' do
+ let(:value) { '9f302fea-f828-4ca9-aef4-e10bd723c0b3' }
+ let(:event_name) { 'my_event' }
+ let(:unknown_event) { 'unknown' }
+ let(:feature) { "usage_data_#{event_name}" }
+
+ context 'with feature enabled' do
+ before do
+ stub_feature_flags(feature => true)
+ end
+
+ it 'tracks redis hll event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(value, event_name)
+
+ described_class.track_usage_event(event_name, value)
+ end
+
+ it 'does not track event when usage ping is not enabled' do
+ stub_application_setting(usage_ping_enabled: false)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ described_class.track_usage_event(event_name, value)
+ end
+
+ it 'raise an error for unknown event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect { described_class.track_usage_event(unknown_event, value) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
+ end
+ end
+
+ context 'with feature disabled' do
+ before do
+ stub_feature_flags(feature => false)
+ end
+
+ it 'does not track event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ described_class.track_usage_event(event_name, value)
+ end
+ end
+ end
end
diff --git a/spec/models/design_management/design_collection_spec.rb b/spec/models/design_management/design_collection_spec.rb
index 33f9d3b988f..8575cc80b5b 100644
--- a/spec/models/design_management/design_collection_spec.rb
+++ b/spec/models/design_management/design_collection_spec.rb
@@ -3,8 +3,9 @@ require 'spec_helper'
RSpec.describe DesignManagement::DesignCollection do
include DesignManagementTestHelpers
+ using RSpec::Parameterized::TableSyntax
- let_it_be(:issue, reload: true) { create(:issue) }
+ let_it_be(:issue, refind: true) { create(:issue) }
subject(:collection) { described_class.new(issue) }
@@ -45,6 +46,61 @@ RSpec.describe DesignManagement::DesignCollection do
end
end
+ describe "#copy_state", :clean_gitlab_redis_shared_state do
+ it "defaults to ready" do
+ expect(collection).to be_copy_ready
+ end
+
+ it "persists its state changes between initializations" do
+ collection.start_copy!
+
+ expect(described_class.new(issue)).to be_copy_in_progress
+ end
+
+ where(:state, :can_start, :can_end, :can_error, :can_reset) do
+ "ready" | true | false | true | true
+ "in_progress" | false | true | true | true
+ "error" | false | false | false | true
+ end
+
+ with_them do
+ it "maintains state machine transition rules", :aggregate_failures do
+ collection.copy_state = state
+
+ expect(collection.can_start_copy?).to eq(can_start)
+ expect(collection.can_end_copy?).to eq(can_end)
+ end
+ end
+
+ describe "clearing the redis cached state when state changes back to ready" do
+ def redis_copy_state
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(collection.send(:copy_state_cache_key))
+ end
+ end
+
+ def fire_state_events(*events)
+ events.each do |event|
+ collection.fire_copy_state_event(event)
+ end
+ end
+
+ it "clears the cached state on end_copy!", :aggregate_failures do
+ fire_state_events(:start)
+
+ expect { collection.end_copy! }.to change { redis_copy_state }.from("in_progress").to(nil)
+ expect(collection).to be_copy_ready
+ end
+
+ it "clears the cached state on reset_copy!", :aggregate_failures do
+ fire_state_events(:start, :error)
+
+ expect { collection.reset_copy! }.to change { redis_copy_state }.from("error").to(nil)
+ expect(collection).to be_copy_ready
+ end
+ end
+ end
+
describe "#versions" do
it "includes versions for all designs" do
version_1 = create(:design_version)