debian-mirror-gitlab/app/workers/process_commit_worker.rb

84 lines
3.1 KiB
Ruby
Raw Normal View History

2018-11-08 19:23:39 +05:30
# frozen_string_literal: true
2019-02-15 15:39:39 +05:30
# Worker for processing individual commit messages pushed to a repository.
2017-08-17 22:00:37 +05:30
#
2019-10-12 21:52:04 +05:30
# Jobs for this worker are scheduled for every commit that contains mentionable
# references in its message and does not exist in the upstream project. As a
2017-08-17 22:00:37 +05:30
# result of this the workload of this worker should be kept to a bare minimum.
# Consider using an extra worker if you need to add any extra (and potentially
# slow) processing of commits.
class ProcessCommitWorker
2018-03-17 18:26:18 +05:30
include ApplicationWorker
2017-08-17 22:00:37 +05:30
2019-12-21 20:55:43 +05:30
feature_category :source_code_management
2019-12-26 22:10:19 +05:30
latency_sensitive_worker!
2019-12-21 20:55:43 +05:30
2017-08-17 22:00:37 +05:30
# project_id - The ID of the project this commit belongs to.
# user_id - The ID of the user that pushed the commit.
# commit_hash - Hash containing commit details to use for constructing a
# Commit object without having to use the Git repository.
# default - The data was pushed to the default branch.
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def perform(project_id, user_id, commit_hash, default = false)
project = Project.find_by(id: project_id)
return unless project
user = User.find_by(id: user_id)
return unless user
commit = build_commit(project, commit_hash)
author = commit.author || user
process_commit_message(project, commit, user, author, default)
update_issue_metrics(commit, author)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def process_commit_message(project, commit, user, author, default = false)
2018-03-27 19:54:05 +05:30
# Ignore closing references from GitLab-generated commit messages.
find_closing_issues = default && !commit.merged_merge_request?(user)
closed_issues = find_closing_issues ? commit.closes_issues(user) : []
2017-08-17 22:00:37 +05:30
2018-03-27 19:54:05 +05:30
close_issues(project, user, author, commit, closed_issues) if closed_issues.any?
2017-08-17 22:00:37 +05:30
commit.create_cross_references!(author, closed_issues)
end
def close_issues(project, user, author, commit, issues)
# We don't want to run permission related queries for every single issue,
2018-03-27 19:54:05 +05:30
# therefore we use IssueCollection here and skip the authorization check in
2017-08-17 22:00:37 +05:30
# Issues::CloseService#execute.
IssueCollection.new(issues).updatable_by_user(user).each do |issue|
2017-09-10 17:25:29 +05:30
Issues::CloseService.new(project, author)
2019-09-04 21:01:54 +05:30
.close_issue(issue, closed_via: commit)
2017-08-17 22:00:37 +05:30
end
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def update_issue_metrics(commit, author)
mentioned_issues = commit.all_references(author).issues
return if mentioned_issues.empty?
2017-09-10 17:25:29 +05:30
Issue::Metrics.where(issue_id: mentioned_issues.map(&:id), first_mentioned_in_commit_at: nil)
.update_all(first_mentioned_in_commit_at: commit.committed_date)
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def build_commit(project, hash)
date_suffix = '_date'
# When processing Sidekiq payloads various timestamps are stored as Strings.
# Commit in turn expects Time-like instances upon input, so we have to
# manually parse these values.
hash.each do |key, value|
if key.to_s.end_with?(date_suffix) && value.is_a?(String)
hash[key] = Time.parse(value)
end
end
Commit.from_hash(hash, project)
end
end