diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-18 03:09:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-18 03:09:28 +0000 |
commit | 37ea4b5fbf55e039a2255f0f5d5508e5f479775c (patch) | |
tree | d64f686008ae7ef96f6ffd3cd498880022af581a | |
parent | cf9694dd845a10c40449f2cfa539af1836f5c6e9 (diff) | |
download | gitlab-ce-37ea4b5fbf55e039a2255f0f5d5508e5f479775c.tar.gz |
Add latest changes from gitlab-org/gitlab@master
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 - – - - 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 + – + - 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) |