Send EmailsOnPush email when branch or tag is created or deleted.
This commit is contained in:
parent
dbd347bfa0
commit
bf235053ad
|
@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date.
|
||||||
|
|
||||||
v 7.10.0 (unreleased)
|
v 7.10.0 (unreleased)
|
||||||
- Add a service to support external wikis (Hannes Rosenögger)
|
- Add a service to support external wikis (Hannes Rosenögger)
|
||||||
|
- Send EmailsOnPush email when branch or tag is created or deleted.
|
||||||
|
|
||||||
v 7.9.0 (unreleased)
|
v 7.9.0 (unreleased)
|
||||||
- Add HipChat integration documentation (Stan Hu)
|
- Add HipChat integration documentation (Stan Hu)
|
||||||
|
|
|
@ -16,31 +16,59 @@ module Emails
|
||||||
subject: subject("Project was moved"))
|
subject: subject("Project was moved"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def repository_push_email(project_id, recipient, author_id, branch, compare, reverse_compare = false, send_from_committer_email = false, disable_diffs = false)
|
def repository_push_email(project_id, recipient, author_id, ref, action, compare, reverse_compare = false, send_from_committer_email = false, disable_diffs = false)
|
||||||
@project = Project.find(project_id)
|
@project = Project.find(project_id)
|
||||||
@author = User.find(author_id)
|
@author = User.find(author_id)
|
||||||
@reverse_compare = reverse_compare
|
@reverse_compare = reverse_compare
|
||||||
@compare = compare
|
@compare = compare
|
||||||
@commits = Commit.decorate(compare.commits)
|
@ref_name = Gitlab::Git.ref_name(ref)
|
||||||
@diffs = compare.diffs
|
@ref_type = Gitlab::Git.tag_ref?(ref) ? "tag" : "branch"
|
||||||
@branch = Gitlab::Git.ref_name(branch)
|
@action = action
|
||||||
@disable_diffs = disable_diffs
|
@disable_diffs = disable_diffs
|
||||||
|
|
||||||
@subject = "[#{@project.path_with_namespace}][#{@branch}] "
|
if @compare
|
||||||
|
@commits = Commit.decorate(compare.commits)
|
||||||
|
@diffs = compare.diffs
|
||||||
|
end
|
||||||
|
|
||||||
if @commits.length > 1
|
@action_name =
|
||||||
@target_url = namespace_project_compare_url(@project.namespace,
|
case action
|
||||||
@project,
|
when :create
|
||||||
from: Commit.new(@compare.base),
|
"pushed new"
|
||||||
to: Commit.new(@compare.head))
|
when :delete
|
||||||
@subject << "Deleted " if @reverse_compare
|
"deleted"
|
||||||
@subject << "#{@commits.length} commits: #{@commits.first.title}"
|
else
|
||||||
|
"pushed to"
|
||||||
|
end
|
||||||
|
|
||||||
|
@subject = "[#{@project.path_with_namespace}]"
|
||||||
|
@subject << "[#{@ref_name}]" if action == :push
|
||||||
|
@subject << " "
|
||||||
|
|
||||||
|
if action == :push
|
||||||
|
if @commits.length > 1
|
||||||
|
@target_url = namespace_project_compare_url(@project.namespace,
|
||||||
|
@project,
|
||||||
|
from: Commit.new(@compare.base),
|
||||||
|
to: Commit.new(@compare.head))
|
||||||
|
@subject << "Deleted " if @reverse_compare
|
||||||
|
@subject << "#{@commits.length} commits: #{@commits.first.title}"
|
||||||
|
else
|
||||||
|
@target_url = namespace_project_commit_url(@project.namespace,
|
||||||
|
@project, @commits.first)
|
||||||
|
|
||||||
|
@subject << "Deleted 1 commit: " if @reverse_compare
|
||||||
|
@subject << @commits.first.title
|
||||||
|
end
|
||||||
else
|
else
|
||||||
@target_url = namespace_project_commit_url(@project.namespace,
|
unless action == :delete
|
||||||
@project, @commits.first)
|
@target_url = namespace_project_tree_url(@project.namespace,
|
||||||
|
@project, @ref_name)
|
||||||
|
end
|
||||||
|
|
||||||
@subject << "Deleted 1 commit: " if @reverse_compare
|
subject_action = @action_name.dup
|
||||||
@subject << @commits.first.title
|
subject_action[0] = subject_action[0].capitalize
|
||||||
|
@subject << "#{subject_action} #{@ref_type} #{@ref_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@disable_footer = true
|
@disable_footer = true
|
||||||
|
|
|
@ -36,7 +36,7 @@ class EmailsOnPushService < Service
|
||||||
end
|
end
|
||||||
|
|
||||||
def supported_events
|
def supported_events
|
||||||
%w(push)
|
%w(push tag_push)
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute(push_data)
|
def execute(push_data)
|
||||||
|
|
|
@ -1,66 +1,67 @@
|
||||||
%h3 #{@author.name} pushed to #{@branch} at #{link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project)}
|
%h3 #{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project)}
|
||||||
|
|
||||||
- if @reverse_compare
|
- if @compare
|
||||||
%p
|
- if @reverse_compare
|
||||||
%strong WARNING:
|
%p
|
||||||
The push did not contain any new commits, but force pushed to delete the commits and changes below.
|
%strong WARNING:
|
||||||
|
The push did not contain any new commits, but force pushed to delete the commits and changes below.
|
||||||
|
|
||||||
%h4
|
%h4
|
||||||
= @reverse_compare ? "Deleted commits:" : "Commits:"
|
= @reverse_compare ? "Deleted commits:" : "Commits:"
|
||||||
|
|
||||||
%ul
|
%ul
|
||||||
- @commits.each do |commit|
|
- @commits.each do |commit|
|
||||||
%li
|
%li
|
||||||
%strong #{link_to commit.short_id, namespace_project_commit_url(@project.namespace, @project, commit)}
|
%strong #{link_to commit.short_id, namespace_project_commit_url(@project.namespace, @project, commit)}
|
||||||
%div
|
%div
|
||||||
%span by #{commit.author_name}
|
%span by #{commit.author_name}
|
||||||
%i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
|
%i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
|
||||||
%pre.commit-message
|
%pre.commit-message
|
||||||
= commit.safe_message
|
= commit.safe_message
|
||||||
|
|
||||||
%h4 #{pluralize @diffs.count, "changed file"}:
|
%h4 #{pluralize @diffs.count, "changed file"}:
|
||||||
|
|
||||||
%ul
|
%ul
|
||||||
- @diffs.each_with_index do |diff, i|
|
- @diffs.each_with_index do |diff, i|
|
||||||
%li.file-stats
|
%li.file-stats
|
||||||
%a{href: "#{@target_url if @disable_diffs}#diff-#{i}" }
|
%a{href: "#{@target_url if @disable_diffs}#diff-#{i}" }
|
||||||
- if diff.deleted_file
|
- if diff.deleted_file
|
||||||
%span.deleted-file
|
%span.deleted-file
|
||||||
−
|
−
|
||||||
|
= diff.old_path
|
||||||
|
- elsif diff.renamed_file
|
||||||
= diff.old_path
|
= diff.old_path
|
||||||
- elsif diff.renamed_file
|
→
|
||||||
= diff.old_path
|
= diff.new_path
|
||||||
→
|
- elsif diff.new_file
|
||||||
= diff.new_path
|
%span.new-file
|
||||||
- elsif diff.new_file
|
+
|
||||||
%span.new-file
|
= diff.new_path
|
||||||
+
|
- else
|
||||||
= diff.new_path
|
= diff.new_path
|
||||||
- else
|
|
||||||
= diff.new_path
|
|
||||||
|
|
||||||
- unless @disable_diffs
|
- unless @disable_diffs
|
||||||
%h4 Changes:
|
%h4 Changes:
|
||||||
- @diffs.each_with_index do |diff, i|
|
- @diffs.each_with_index do |diff, i|
|
||||||
%li{id: "diff-#{i}"}
|
%li{id: "diff-#{i}"}
|
||||||
%a{href: @target_url + "#diff-#{i}"}
|
%a{href: @target_url + "#diff-#{i}"}
|
||||||
- if diff.deleted_file
|
- if diff.deleted_file
|
||||||
%strong
|
%strong
|
||||||
= diff.old_path
|
= diff.old_path
|
||||||
deleted
|
deleted
|
||||||
- elsif diff.renamed_file
|
- elsif diff.renamed_file
|
||||||
%strong
|
%strong
|
||||||
= diff.old_path
|
= diff.old_path
|
||||||
→
|
→
|
||||||
%strong
|
%strong
|
||||||
= diff.new_path
|
= diff.new_path
|
||||||
- else
|
- else
|
||||||
%strong
|
%strong
|
||||||
= diff.new_path
|
= diff.new_path
|
||||||
%hr
|
%hr
|
||||||
%pre
|
%pre
|
||||||
= color_email_diff(diff.diff)
|
= color_email_diff(diff.diff)
|
||||||
%br
|
%br
|
||||||
|
|
||||||
- if @compare.timeout
|
- if @compare.timeout
|
||||||
%h5 Huge diff. To prevent performance issues changes are hidden
|
%h5 Huge diff. To prevent performance issues changes are hidden
|
||||||
|
|
|
@ -1,47 +1,49 @@
|
||||||
#{@author.name} pushed to #{@branch} at #{@project.name_with_namespace}
|
#{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{@project.name_with_namespace}
|
||||||
\
|
- if @compare
|
||||||
\
|
|
||||||
- if @reverse_compare
|
|
||||||
WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below.
|
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
= @reverse_compare ? "Deleted commits:" : "Commits:"
|
- if @reverse_compare
|
||||||
- @commits.each do |commit|
|
WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below.
|
||||||
#{commit.short_id} by #{commit.author_name} at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
|
|
||||||
#{commit.safe_message}
|
|
||||||
\- - - - -
|
|
||||||
\
|
|
||||||
\
|
|
||||||
#{pluralize @diffs.count, "changed file"}:
|
|
||||||
\
|
|
||||||
- @diffs.each do |diff|
|
|
||||||
- if diff.deleted_file
|
|
||||||
\- − #{diff.old_path}
|
|
||||||
- elsif diff.renamed_file
|
|
||||||
\- #{diff.old_path} → #{diff.new_path}
|
|
||||||
- elsif diff.new_file
|
|
||||||
\- + #{diff.new_path}
|
|
||||||
- else
|
|
||||||
\- #{diff.new_path}
|
|
||||||
- unless @disable_diffs
|
|
||||||
\
|
|
||||||
\
|
|
||||||
Changes:
|
|
||||||
- @diffs.each do |diff|
|
|
||||||
\
|
\
|
||||||
\=====================================
|
\
|
||||||
|
= @reverse_compare ? "Deleted commits:" : "Commits:"
|
||||||
|
- @commits.each do |commit|
|
||||||
|
#{commit.short_id} by #{commit.author_name} at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
|
||||||
|
#{commit.safe_message}
|
||||||
|
\- - - - -
|
||||||
|
\
|
||||||
|
\
|
||||||
|
#{pluralize @diffs.count, "changed file"}:
|
||||||
|
\
|
||||||
|
- @diffs.each do |diff|
|
||||||
- if diff.deleted_file
|
- if diff.deleted_file
|
||||||
#{diff.old_path} deleted
|
\- − #{diff.old_path}
|
||||||
- elsif diff.renamed_file
|
- elsif diff.renamed_file
|
||||||
#{diff.old_path} → #{diff.new_path}
|
\- #{diff.old_path} → #{diff.new_path}
|
||||||
|
- elsif diff.new_file
|
||||||
|
\- + #{diff.new_path}
|
||||||
- else
|
- else
|
||||||
= diff.new_path
|
\- #{diff.new_path}
|
||||||
\=====================================
|
- unless @disable_diffs
|
||||||
!= diff.diff
|
\
|
||||||
- if @compare.timeout
|
\
|
||||||
\
|
Changes:
|
||||||
\
|
- @diffs.each do |diff|
|
||||||
Huge diff. To prevent performance issues it was hidden
|
\
|
||||||
\
|
\=====================================
|
||||||
\
|
- if diff.deleted_file
|
||||||
View it on GitLab: #{@target_url}
|
#{diff.old_path} deleted
|
||||||
|
- elsif diff.renamed_file
|
||||||
|
#{diff.old_path} → #{diff.new_path}
|
||||||
|
- else
|
||||||
|
= diff.new_path
|
||||||
|
\=====================================
|
||||||
|
!= diff.diff
|
||||||
|
- if @compare.timeout
|
||||||
|
\
|
||||||
|
\
|
||||||
|
Huge diff. To prevent performance issues it was hidden
|
||||||
|
- if @target_url
|
||||||
|
\
|
||||||
|
\
|
||||||
|
View it on GitLab: #{@target_url}
|
||||||
|
|
|
@ -5,24 +5,32 @@ class EmailsOnPushWorker
|
||||||
project = Project.find(project_id)
|
project = Project.find(project_id)
|
||||||
before_sha = push_data["before"]
|
before_sha = push_data["before"]
|
||||||
after_sha = push_data["after"]
|
after_sha = push_data["after"]
|
||||||
branch = push_data["ref"]
|
ref = push_data["ref"]
|
||||||
author_id = push_data["user_id"]
|
author_id = push_data["user_id"]
|
||||||
|
|
||||||
if Gitlab::Git.blank_ref?(before_sha) || Gitlab::Git.blank_ref?(after_sha)
|
action =
|
||||||
# skip if new branch was pushed or branch was removed
|
if Gitlab::Git.blank_ref?(before_sha)
|
||||||
return true
|
:create
|
||||||
end
|
elsif Gitlab::Git.blank_ref?(after_sha)
|
||||||
|
:delete
|
||||||
|
else
|
||||||
|
:push
|
||||||
|
end
|
||||||
|
|
||||||
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
|
compare = nil
|
||||||
|
reverse_compare = false
|
||||||
|
if action == :push
|
||||||
|
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
|
||||||
|
|
||||||
return false if compare.same
|
return false if compare.same
|
||||||
|
|
||||||
if compare.commits.empty?
|
if compare.commits.empty?
|
||||||
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
|
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
|
||||||
|
|
||||||
reverse_compare = true
|
reverse_compare = true
|
||||||
|
|
||||||
return false if compare.commits.empty?
|
return false if compare.commits.empty?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
recipients.split(" ").each do |recipient|
|
recipients.split(" ").each do |recipient|
|
||||||
|
@ -30,7 +38,8 @@ class EmailsOnPushWorker
|
||||||
project_id,
|
project_id,
|
||||||
recipient,
|
recipient,
|
||||||
author_id,
|
author_id,
|
||||||
branch,
|
ref,
|
||||||
|
action,
|
||||||
compare,
|
compare,
|
||||||
reverse_compare,
|
reverse_compare,
|
||||||
send_from_committer_email,
|
send_from_committer_email,
|
||||||
|
|
|
@ -640,6 +640,100 @@ describe Notify do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'email on push for a created branch' do
|
||||||
|
let(:example_site_path) { root_path }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") }
|
||||||
|
|
||||||
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/heads/master', :create, nil) }
|
||||||
|
|
||||||
|
it 'is sent as the author' do
|
||||||
|
sender = subject.header[:from].addrs[0]
|
||||||
|
expect(sender.display_name).to eq(user.name)
|
||||||
|
expect(sender.address).to eq(gitlab_sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is sent to recipient' do
|
||||||
|
is_expected.to deliver_to 'devs@company.name'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has the correct subject' do
|
||||||
|
is_expected.to have_subject /Pushed new branch master/
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains a link to the branch' do
|
||||||
|
is_expected.to have_body_text /#{tree_path}/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'email on push for a created tag' do
|
||||||
|
let(:example_site_path) { root_path }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") }
|
||||||
|
|
||||||
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/tags/v1.0', :create, nil) }
|
||||||
|
|
||||||
|
it 'is sent as the author' do
|
||||||
|
sender = subject.header[:from].addrs[0]
|
||||||
|
expect(sender.display_name).to eq(user.name)
|
||||||
|
expect(sender.address).to eq(gitlab_sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is sent to recipient' do
|
||||||
|
is_expected.to deliver_to 'devs@company.name'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has the correct subject' do
|
||||||
|
is_expected.to have_subject /Pushed new tag v1\.0/
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains a link to the tag' do
|
||||||
|
is_expected.to have_body_text /#{tree_path}/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'email on push for a deleted branch' do
|
||||||
|
let(:example_site_path) { root_path }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/heads/master', :delete, nil) }
|
||||||
|
|
||||||
|
it 'is sent as the author' do
|
||||||
|
sender = subject.header[:from].addrs[0]
|
||||||
|
expect(sender.display_name).to eq(user.name)
|
||||||
|
expect(sender.address).to eq(gitlab_sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is sent to recipient' do
|
||||||
|
is_expected.to deliver_to 'devs@company.name'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has the correct subject' do
|
||||||
|
is_expected.to have_subject /Deleted branch master/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'email on push for a deleted tag' do
|
||||||
|
let(:example_site_path) { root_path }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/tags/v1.0', :delete, nil) }
|
||||||
|
|
||||||
|
it 'is sent as the author' do
|
||||||
|
sender = subject.header[:from].addrs[0]
|
||||||
|
expect(sender.display_name).to eq(user.name)
|
||||||
|
expect(sender.address).to eq(gitlab_sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is sent to recipient' do
|
||||||
|
is_expected.to deliver_to 'devs@company.name'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has the correct subject' do
|
||||||
|
is_expected.to have_subject /Deleted tag v1\.0/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'email on push with multiple commits' do
|
describe 'email on push with multiple commits' do
|
||||||
let(:example_site_path) { root_path }
|
let(:example_site_path) { root_path }
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
|
@ -648,7 +742,7 @@ describe Notify do
|
||||||
let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base), to: Commit.new(compare.head)) }
|
let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base), to: Commit.new(compare.head)) }
|
||||||
let(:send_from_committer_email) { false }
|
let(:send_from_committer_email) { false }
|
||||||
|
|
||||||
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare, false, send_from_committer_email) }
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/heads/master', :push, compare, false, send_from_committer_email) }
|
||||||
|
|
||||||
it 'is sent as the author' do
|
it 'is sent as the author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
|
@ -736,7 +830,7 @@ describe Notify do
|
||||||
let(:commits) { Commit.decorate(compare.commits) }
|
let(:commits) { Commit.decorate(compare.commits) }
|
||||||
let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
|
let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
|
||||||
|
|
||||||
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) }
|
subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'refs/heads/master', :push, compare) }
|
||||||
|
|
||||||
it 'is sent as the author' do
|
it 'is sent as the author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
|
|
Loading…
Reference in New Issue