Commit bf235053 authored by Douwe Maan's avatar Douwe Maan

Send EmailsOnPush email when branch or tag is created or deleted.

parent dbd347bf
...@@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -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 ...@@ -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
@action_name =
case action
when :create
"pushed new"
when :delete
"deleted"
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)
if @commits.length > 1 @subject << "Deleted 1 commit: " if @reverse_compare
@target_url = namespace_project_compare_url(@project.namespace, @subject << @commits.first.title
@project, end
from: Commit.new(@compare.base),
to: Commit.new(@compare.head))
@subject << "Deleted " if @reverse_compare
@subject << "#{@commits.length} commits: #{@commits.first.title}"
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 ...@@ -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)
......
%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
&minus; &minus;
= diff.old_path
- elsif diff.renamed_file
= diff.old_path = diff.old_path
- elsif diff.renamed_file &rarr;
= diff.old_path
&rarr;
= diff.new_path
- elsif diff.new_file
%span.new-file
&plus;
= diff.new_path = diff.new_path
- else - elsif diff.new_file
= diff.new_path %span.new-file
&plus;
- unless @disable_diffs = diff.new_path
%h4 Changes: - else
- @diffs.each_with_index do |diff, i|
%li{id: "diff-#{i}"}
%a{href: @target_url + "#diff-#{i}"}
- if diff.deleted_file
%strong
= diff.old_path
deleted
- elsif diff.renamed_file
%strong
= diff.old_path
&rarr;
%strong
= diff.new_path = diff.new_path
- else
%strong
= diff.new_path
%hr
%pre
= color_email_diff(diff.diff)
%br
- if @compare.timeout - unless @disable_diffs
%h5 Huge diff. To prevent performance issues changes are hidden %h4 Changes:
- @diffs.each_with_index do |diff, i|
%li{id: "diff-#{i}"}
%a{href: @target_url + "#diff-#{i}"}
- if diff.deleted_file
%strong
= diff.old_path
deleted
- elsif diff.renamed_file
%strong
= diff.old_path
&rarr;
%strong
= diff.new_path
- else
%strong
= diff.new_path
%hr
%pre
= color_email_diff(diff.diff)
%br
- if @compare.timeout
%h5 Huge diff. To prevent performance issues changes are hidden
#{@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} \
\- - - - - = @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")}
#{pluralize @diffs.count, "changed file"}: #{commit.safe_message}
\ \- - - - -
- @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
\ \
#{pluralize @diffs.count, "changed file"}:
\ \
Changes:
- @diffs.each do |diff| - @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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment