Skip to content

Instantly share code, notes, and snippets.

@cpruitt
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save cpruitt/5fdaec6de5aa12cc6080 to your computer and use it in GitHub Desktop.

Select an option

Save cpruitt/5fdaec6de5aa12cc6080 to your computer and use it in GitHub Desktop.
Inspyre Git post-commit to send email notifications to specific people for specific branches (2.0)
#!/usr/bin/env ruby
require "action_mailer"
options = {
# The name of this project / repository
# to be used in the emailed notifications
project_name: "My Development Project",
# Hash of branch specific notification settings.
# Hash keys are individual symbols or Regexp objects (or arrays
# thereof) specifying the branches to send notifications to. The
# special key :default specifies notification settings for all
# defined branches unless a specific branch overrides it. The key
# can also be an array of mixed symbols / regexs.
#
# Each entry in the :branches hash is, itself, a hash with
# two possible keys:
# :subject - String to be used in the subject
# The subject string which can have placeholders for: {branch} and {project}
# If left out a reasonable subject line is used by default.
# :mail_to - Array of recipient email addresses
branches: {
default: {
mail_to: [ '[email protected]', '[email protected]', '[email protected]' ]
},
[:master, :develop] => {}
},
# SMTP mailer settings. Used by ActionMailer
mailer: {
address: "smtp.example.com",
port: 587,
domain: "example.com",
user_name: "[email protected]",
password: "p@$$w0rd",
authentication: :login,
enable_starttls_auto: true
},
# Displays feedback about the notification.
# Using this will cause the git commit to exit more slowly.
# Setting to false will fork the notification process allowing
# the git commit to complete and exit immediately.
chatty: true,
# Set :markup to :markdown to process commit messages as markdown text.
# Markdown formatting: https://github.com/bhollis/maruku/blob/master/docs/markdown_syntax.md
markup: :markdown,
}
######################################################################
# #
# No need to edit anything past this point. #
# #
######################################################################
begin
require 'maruku'
@markdownable = true
rescue LoadError
puts "==== Enable markdown formatting by installing the maruku gem: $ gem install maruku ===="
puts " Silence this notice by removing it from post-commit or by installing the gem."
@markdownable = false
end
class CommitHandler
def initialize(config = {})
@config = {
chatty: false
}.merge(config)
expand_branch_settings
# Find current branch
@current_branch = nil
git_branches = (`git branch`).split("\n").each { |b| @current_branch = b[2..-1] if b[0] == "*" }
@current_branch.downcase!
end
def run
branch_options = branch_options_for_current_branch
if branch_options
tell("Sending notification for branch `#{@current_branch}` to:\n" + branch_options[:mail_to].join("\n"))
tell("")
else
tell("Branch `#{@current_branch}` has no notification rules. Nothing to send.")
tell("")
return
end
commit = GitCommit.new
if @config[:markdownable] && @config[:markup] == :markdown
m = []
m << "#{@config[:project_name]}"
m << "=================================================="
m << ""
m << "## New Git Commit on branch: `#{@current_branch}`"
m << "--------------------------------------------------"
m << ""
m << "* __Authored BY:__ #{commit.author}"
m << "* __Committed On:__ #{commit.date}"
m << "* __Commit ID:__ #{commit.commit}"
m << ""
m << "--------------------------------------------------"
m << ""
m << commit.message
m << ""
msg_txt = m.join("\n")
msg = Maruku.new(msg_txt).to_html
else
msg = "<h1>#{@config[:project_name]}</h1><h2>New Git Commit on #{@current_branch}</h2><p style=\"font-family:monospace;\">#{commit.message}</p>"
msg_txt = "New Git Commit\n\n" + commit.message
end
subject = branch_options[:subject]
subject.gsub!(/\{project\}/, @config[:project_name])
subject.gsub!(/\{branch\}/, @current_branch)
mail_using = :smtp
if mail_using == :smtp
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = @config[:mailer]
else
ActionMailer::Base.delivery_method = :sendmail
end
Notifier.notify(branch_options[:mail_to], subject, msg, msg_txt).deliver
tell ""
tell "MAILING NOTIFICATION:"
tell msg
tell ""
tell ""
end
private
def expand_branch_settings
@config[:notification_branches] = {}
@config[:branches] = {} unless @config[:branches].class == Hash
@config[:branches][:default] = {} unless @config[:branches][:default].class == Hash
@config[:branches][:default][:subject] = "NOTIFICATION: New Git commit for {project} on {branch}" unless @config[:branches][:default][:subject]
@config[:branches].each do |branches, settings|
result_settings = @config[:branches][:default].merge(settings)
branches = [branches] unless branches.class == Array
branches.each do |branch|
if branch.kind_of?(Regexp)
@config[:notification_branches][branch] = result_settings
else
@config[:notification_branches][branch.to_s] = result_settings
end
end
end
end
def branch_options_for_current_branch
result = nil
@config[:notification_branches].each do |branch_key, branch_settings|
if branch_key.kind_of?(Regexp)
result = branch_settings if @current_branch =~ branch_key
else
result = branch_settings if @current_branch == branch_key.to_s
end
end
result
end
def tell(msg)
return if !@config[:chatty]
puts(msg)
end
end
class GitCommit
attr_accessor :commit, :author, :date, :message
def initialize
log_lines = `git log -1`.split("\n")
@commit = log_lines.shift.split(' ')[1..-1].join(' ')
@author = log_lines.shift.split(' ')[1..-1].join(' ')
@date = log_lines.shift.split(' ')[1..-1].join(' ')
log_lines.shift
@message = log_lines.collect { |l| l.to_s[4..-1] }.join("\n")
end
end
# ActionMailer notification
class Notifier < ActionMailer::Base
default :from => "[email protected]"
def notify(recips, subject, msg, msg_txt)
mail(:to => recips, :subject => subject) do |format|
format.text { render :text => msg_txt}
format.html { render :text => msg}
end
end
end
if options[:chatty]
CommitHandler.new(options.merge({markdownable: @markdownable})).run
else
fork do
CommitHandler.new(options.merge({markdownable: @markdownable})).run
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment