diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-10 21:07:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-10 21:07:43 +0300 |
commit | 6f0f893bd87535b61e0ecb1ce069eaa7fcb9e5be (patch) | |
tree | 8af92b29c838e9af2fd70f9a4a2314a08f4af922 /app | |
parent | 8b1228b0d409d7751f01d9fb72ebfbbf62399486 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
20 files changed, 173 insertions, 84 deletions
diff --git a/app/assets/javascripts/lib/utils/poll_until_complete.js b/app/assets/javascripts/lib/utils/poll_until_complete.js new file mode 100644 index 00000000000..199d0e6f0f7 --- /dev/null +++ b/app/assets/javascripts/lib/utils/poll_until_complete.js @@ -0,0 +1,42 @@ +import axios from '~/lib/utils/axios_utils'; +import Poll from './poll'; +import httpStatusCodes from './http_status'; + +/** + * Polls an endpoint until it returns either a 200 OK or a error status. + * The Poll-Interval header in the responses are used to determine how + * frequently to poll. + * + * Once a 200 OK is received, the promise resolves with that response. If an + * error status is received, the promise rejects with the error. + * + * @param {string} url - The URL to poll. + * @param {Object} [config] - The config to provide to axios.get(). + * @returns {Promise} + */ +export default (url, config = {}) => + new Promise((resolve, reject) => { + const eTagPoll = new Poll({ + resource: { + axiosGet(data) { + return axios.get(data.url, { + headers: { + 'Content-Type': 'application/json', + }, + ...data.config, + }); + }, + }, + data: { url, config }, + method: 'axiosGet', + successCallback: response => { + if (response.status === httpStatusCodes.OK) { + resolve(response); + eTagPoll.stop(); + } + }, + errorCallback: reject, + }); + + eTagPoll.makeRequest(); + }); diff --git a/app/assets/javascripts/releases/list/components/app.vue b/app/assets/javascripts/releases/list/components/app.vue index a414b3ccd4e..eb63e709ebd 100644 --- a/app/assets/javascripts/releases/list/components/app.vue +++ b/app/assets/javascripts/releases/list/components/app.vue @@ -66,7 +66,7 @@ export default { :svg-path="illustrationPath" :description=" __( - 'Releases mark specific points in a project\'s development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API.', + 'Releases are based on Git tags and mark specific points in a project\'s development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software.', ) " :primary-button-link="documentationLink" diff --git a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb index c680f387a9a..81d97a08a7e 100644 --- a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb +++ b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb @@ -76,6 +76,9 @@ module Types field :last_release_short_version, GraphQL::STRING_TYPE, null: true, description: "Release version the error was last seen" + field :gitlab_commit, GraphQL::STRING_TYPE, + null: true, + description: "GitLab commit SHA attributed to the Error based on the release version" def first_seen DateTime.parse(object.first_seen) diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb index 6c51f650b6a..804e01bfab0 100644 --- a/app/models/ci/bridge.rb +++ b/app/models/ci/bridge.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true module Ci - class Bridge < CommitStatus - include Ci::Processable + class Bridge < Ci::Processable include Ci::Contextable include Ci::PipelineDelegator include Importable diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5edd2f52fc8..2df41bc2a07 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true module Ci - class Build < CommitStatus - include Ci::Processable + class Build < Ci::Processable include Ci::Metadatable include Ci::Contextable include Ci::PipelineDelegator diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ab0a4fd6289..7a48fa8595b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -33,8 +33,7 @@ module Ci has_many :stages, -> { order(position: :asc) }, inverse_of: :pipeline has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline has_many :latest_statuses_ordered_by_stage, -> { latest.order(:stage_idx, :stage) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline - has_many :processables, -> { processables }, - class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline + has_many :processables, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent has_many :variables, class_name: 'Ci::PipelineVariable' diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb new file mode 100644 index 00000000000..9c56aa67e20 --- /dev/null +++ b/app/models/ci/processable.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Ci + class Processable < ::CommitStatus + has_many :needs, class_name: 'Ci::BuildNeed', foreign_key: :build_id, inverse_of: :build + + accepts_nested_attributes_for :needs + + scope :preload_needs, -> { preload(:needs) } + + validates :type, presence: true + + def schedulable? + raise NotImplementedError + end + + def action? + raise NotImplementedError + end + + def when + read_attribute(:when) || 'on_success' + end + + def expanded_environment_name + raise NotImplementedError + end + + def scoped_variables_hash + raise NotImplementedError + end + end +end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 9da49b44cbe..773481da5f9 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -45,7 +45,6 @@ class CommitStatus < ApplicationRecord scope :before_stage, -> (index) { where('stage_idx < ?', index) } scope :for_stage, -> (index) { where(stage_idx: index) } scope :after_stage, -> (index) { where('stage_idx > ?', index) } - scope :processables, -> { where(type: %w[Ci::Build Ci::Bridge]) } scope :for_ids, -> (ids) { where(id: ids) } scope :for_ref, -> (ref) { where(ref: ref) } scope :by_name, -> (name) { where(name: name) } diff --git a/app/models/concerns/ci/processable.rb b/app/models/concerns/ci/processable.rb deleted file mode 100644 index c229358ad17..00000000000 --- a/app/models/concerns/ci/processable.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -module Ci - ## - # This module implements methods that need to be implemented by CI/CD - # entities that are supposed to go through pipeline processing - # services. - # - # - module Processable - extend ActiveSupport::Concern - - included do - has_many :needs, class_name: 'Ci::BuildNeed', foreign_key: :build_id, inverse_of: :build - - accepts_nested_attributes_for :needs - - scope :preload_needs, -> { preload(:needs) } - end - - def schedulable? - raise NotImplementedError - end - - def action? - raise NotImplementedError - end - - def when - read_attribute(:when) || 'on_success' - end - - def expanded_environment_name - raise NotImplementedError - end - - def scoped_variables_hash - raise NotImplementedError - end - end -end diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 4aba70cb124..bf7e0e9580a 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -113,9 +113,8 @@ module ErrorTracking when 'list_issues' sentry_client.list_issues(**opts.symbolize_keys) when 'issue_details' - { - issue: sentry_client.issue_details(**opts.symbolize_keys) - } + issue = sentry_client.issue_details(**opts.symbolize_keys) + { issue: add_gitlab_issue_details(issue) } when 'issue_latest_event' { latest_event: sentry_client.issue_latest_event(**opts.symbolize_keys) @@ -140,6 +139,20 @@ module ErrorTracking private + def add_gitlab_issue_details(issue) + issue.gitlab_commit = match_gitlab_commit(issue.first_release_version) + + issue + end + + def match_gitlab_commit(release_version) + return unless release_version + + commit = project.repository.commit(release_version) + + commit&.id + end + def handle_exceptions yield rescue Sentry::Client::Error => e diff --git a/app/models/release.rb b/app/models/release.rb index 4fac64689ab..823fd61eebd 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -81,6 +81,10 @@ class Release < ApplicationRecord evidence&.summary || {} end + def milestone_titles + self.milestones.map {|m| m.title }.sort.join(", ") + end + private def actual_sha diff --git a/app/presenters/ci/bridge_presenter.rb b/app/presenters/ci/bridge_presenter.rb index ee11cffe355..724e10c26c3 100644 --- a/app/presenters/ci/bridge_presenter.rb +++ b/app/presenters/ci/bridge_presenter.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Ci - class BridgePresenter < CommitStatusPresenter + class BridgePresenter < ProcessablePresenter def detailed_status @detailed_status ||= subject.detailed_status(user) end diff --git a/app/presenters/ci/build_presenter.rb b/app/presenters/ci/build_presenter.rb index 33056a809b7..03cbb57eb84 100644 --- a/app/presenters/ci/build_presenter.rb +++ b/app/presenters/ci/build_presenter.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Ci - class BuildPresenter < CommitStatusPresenter + class BuildPresenter < ProcessablePresenter def erased_by_user? # Build can be erased through API, therefore it does not have # `erased_by` user assigned in that case. diff --git a/app/presenters/ci/processable_presenter.rb b/app/presenters/ci/processable_presenter.rb new file mode 100644 index 00000000000..5a8a6649071 --- /dev/null +++ b/app/presenters/ci/processable_presenter.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Ci + class ProcessablePresenter < CommitStatusPresenter + end +end diff --git a/app/serializers/error_tracking/detailed_error_entity.rb b/app/serializers/error_tracking/detailed_error_entity.rb index fdafa2cf203..7bc2b3ce576 100644 --- a/app/serializers/error_tracking/detailed_error_entity.rb +++ b/app/serializers/error_tracking/detailed_error_entity.rb @@ -8,6 +8,7 @@ module ErrorTracking :external_url, :first_release_last_commit, :first_release_short_version, + :gitlab_commit, :first_seen, :frequency, :gitlab_issue, diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb index 6ba8dac21f0..a452f7aa17a 100644 --- a/app/services/releases/update_service.rb +++ b/app/services/releases/update_service.rb @@ -11,10 +11,13 @@ module Releases return error('params is empty', 400) if empty_params? return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any? - params[:milestones] = milestones if param_for_milestone_titles_provided? + if param_for_milestone_titles_provided? + previous_milestones = release.milestones.map(&:title) + params[:milestones] = milestones + end if release.update(params) - success(tag: existing_tag, release: release) + success(tag: existing_tag, release: release, milestones_updated: milestones_updated?(previous_milestones)) else error(release.errors.messages || '400 Bad request', 400) end @@ -29,5 +32,11 @@ module Releases def empty_params? params.except(:tag).empty? end + + def milestones_updated?(previous_milestones) + return false unless param_for_milestone_titles_provided? + + previous_milestones.to_set != release.milestones.map(&:title) + end end end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index ca050887e0f..6afc326ed37 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -188,3 +188,4 @@ - create_evidence - group_export - self_monitoring_project_create +- self_monitoring_project_delete diff --git a/app/workers/concerns/self_monitoring_project_worker.rb b/app/workers/concerns/self_monitoring_project_worker.rb new file mode 100644 index 00000000000..44dd6866fad --- /dev/null +++ b/app/workers/concerns/self_monitoring_project_worker.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module SelfMonitoringProjectWorker + extend ActiveSupport::Concern + + included do + # This worker falls under Self-monitoring with Monitor::APM group. However, + # self-monitoring is not classified as a feature category but rather as + # Other Functionality. Metrics seems to be the closest feature_category for + # this worker. + feature_category :metrics + end + + LEASE_TIMEOUT = 15.minutes.to_i + EXCLUSIVE_LEASE_KEY = 'self_monitoring_service_creation_deletion' + + class_methods do + # @param job_id [String] + # Job ID that is used to construct the cache keys. + # @return [Hash] + # Returns true if the job is enqueued or in progress and false otherwise. + def in_progress?(job_id) + Gitlab::SidekiqStatus.job_status(Array.wrap(job_id)).first + end + end + + private + + def lease_key + EXCLUSIVE_LEASE_KEY + end + + def lease_timeout + self.class::LEASE_TIMEOUT + end +end diff --git a/app/workers/self_monitoring_project_create_worker.rb b/app/workers/self_monitoring_project_create_worker.rb index 69bc5431ff7..429ac8aacc4 100644 --- a/app/workers/self_monitoring_project_create_worker.rb +++ b/app/workers/self_monitoring_project_create_worker.rb @@ -3,38 +3,11 @@ class SelfMonitoringProjectCreateWorker include ApplicationWorker include ExclusiveLeaseGuard - - # This worker falls under Self-monitoring with Monitor::APM group. However, - # self-monitoring is not classified as a feature category but rather as - # Other Functionality. Metrics seems to be the closest feature_category for - # this worker. - feature_category :metrics - - LEASE_TIMEOUT = 15.minutes.to_i - - EXCLUSIVE_LEASE_KEY = 'self_monitoring_service_creation_deletion' + include SelfMonitoringProjectWorker def perform try_obtain_lease do Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute end end - - # @param job_id [String] - # Job ID that is used to construct the cache keys. - # @return [Hash] - # Returns true if the job is enqueued or in progress and false otherwise. - def self.in_progress?(job_id) - Gitlab::SidekiqStatus.job_status(Array.wrap(job_id)).first - end - - private - - def lease_key - EXCLUSIVE_LEASE_KEY - end - - def lease_timeout - LEASE_TIMEOUT - end end diff --git a/app/workers/self_monitoring_project_delete_worker.rb b/app/workers/self_monitoring_project_delete_worker.rb new file mode 100644 index 00000000000..07a7d3f6c45 --- /dev/null +++ b/app/workers/self_monitoring_project_delete_worker.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class SelfMonitoringProjectDeleteWorker + include ApplicationWorker + include ExclusiveLeaseGuard + include SelfMonitoringProjectWorker + + def perform + try_obtain_lease do + Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService.new.execute + end + end +end |