2018-11-18 11:00:15 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
class PushEvent < Event
|
|
|
|
# This validation exists so we can't accidentally use PushEvent with a
|
|
|
|
# different "action" value.
|
|
|
|
validate :validate_push_action
|
|
|
|
|
|
|
|
# The project is required to build links to commits, commit ranges, etc.
|
|
|
|
#
|
|
|
|
# We're just validating the presence of the ID here as foreign key constraints
|
|
|
|
# should ensure the ID points to a valid project.
|
|
|
|
validates :project_id, presence: true
|
|
|
|
|
|
|
|
# These fields are also not used for push events, thus storing them would be a
|
|
|
|
# waste.
|
|
|
|
validates :target_id, absence: true
|
|
|
|
validates :target_type, absence: true
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
delegate :branch?, to: :push_event_payload
|
|
|
|
delegate :tag?, to: :push_event_payload
|
|
|
|
delegate :commit_from, to: :push_event_payload
|
|
|
|
delegate :commit_to, to: :push_event_payload
|
|
|
|
delegate :ref_type, to: :push_event_payload
|
|
|
|
delegate :commit_title, to: :push_event_payload
|
|
|
|
|
|
|
|
delegate :commit_count, to: :push_event_payload
|
|
|
|
alias_method :commits_count, :commit_count
|
|
|
|
|
|
|
|
# Returns events of pushes that either pushed to an existing ref or created a
|
|
|
|
# new one.
|
|
|
|
def self.created_or_pushed
|
|
|
|
actions = [
|
|
|
|
PushEventPayload.actions[:pushed],
|
|
|
|
PushEventPayload.actions[:created]
|
|
|
|
]
|
|
|
|
|
|
|
|
joins(:push_event_payload)
|
|
|
|
.where(push_event_payloads: { action: actions })
|
|
|
|
end
|
|
|
|
|
|
|
|
# Returns events of pushes to a branch.
|
|
|
|
def self.branch_events
|
|
|
|
ref_type = PushEventPayload.ref_types[:branch]
|
|
|
|
|
|
|
|
joins(:push_event_payload)
|
|
|
|
.where(push_event_payloads: { ref_type: ref_type })
|
|
|
|
end
|
|
|
|
|
|
|
|
# Returns PushEvent instances for which no merge requests have been created.
|
|
|
|
def self.without_existing_merge_requests
|
|
|
|
existing_mrs = MergeRequest.except(:order, :where)
|
|
|
|
.select(1)
|
|
|
|
.where('merge_requests.source_project_id = events.project_id')
|
|
|
|
.where('merge_requests.source_branch = push_event_payloads.ref')
|
|
|
|
.where(state: :opened)
|
|
|
|
|
|
|
|
# For reasons unknown the use of #eager_load will result in the
|
|
|
|
# "push_event_payload" association not being set. Because of this we're
|
|
|
|
# using "joins" here, which does mean an additional query needs to be
|
|
|
|
# executed in order to retrieve the "push_event_association" when the
|
|
|
|
# returned PushEvent is used.
|
|
|
|
joins(:push_event_payload)
|
|
|
|
.where('NOT EXISTS (?)', existing_mrs)
|
|
|
|
.created_or_pushed
|
|
|
|
.branch_events
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
def self.sti_name
|
|
|
|
PUSHED
|
|
|
|
end
|
|
|
|
|
2019-12-16 22:33:55 +05:30
|
|
|
def push_action?
|
2017-09-10 17:25:29 +05:30
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def push_with_commits?
|
|
|
|
!!(commit_from && commit_to)
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid_push?
|
|
|
|
push_event_payload.ref.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_ref?
|
|
|
|
push_event_payload.created?
|
|
|
|
end
|
|
|
|
|
|
|
|
def rm_ref?
|
|
|
|
push_event_payload.removed?
|
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
def md_ref?
|
|
|
|
!(rm_ref? || new_ref?)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def ref_name
|
|
|
|
push_event_payload.ref
|
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
alias_method :branch_name, :ref_name
|
|
|
|
alias_method :tag_name, :ref_name
|
2017-09-10 17:25:29 +05:30
|
|
|
|
|
|
|
def commit_id
|
|
|
|
commit_to || commit_from
|
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
def last_push_to_non_root?
|
|
|
|
branch? && project.default_branch != branch_name
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def validate_push_action
|
|
|
|
return if action == PUSHED
|
|
|
|
|
|
|
|
errors.add(:action, "the action #{action.inspect} is not valid")
|
|
|
|
end
|
|
|
|
end
|