Skip to content

Instantly share code, notes, and snippets.

@anna-is-cute
Last active December 22, 2023 09:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anna-is-cute/eea672b90010a150d4ac to your computer and use it in GitHub Desktop.
Save anna-is-cute/eea672b90010a150d4ac to your computer and use it in GitHub Desktop.
Bamboo IRC Notifications

Bamboo IRC Notifications

Create a new stage. Make sure it runs last. Create a job within this stage. Choose the Script job.

Paste in the shell script below for the script. You may need to change the path of ruby.

For the argument field, insert the following: ${bamboo.buildResultsUrl} ${bamboo.planKey}

read -d '' RUBY_SCRIPT <<"EOF"
require 'socket'
require 'open-uri'
require 'json'
Channel = Struct.new(:name, :key)
# YOU MAY EDIT BELOW #
EVENTS = %w(successful failed)
IRC_INFO = {
server: 'irc.example.com',
port: 6667,
nickname: 'MyBotName',
password: nil,
username: nil,
ircname: nil
}
IRC_OPTIONS = {
join_channels: [
Channel.new('#somechannel', nil) # (name, key) leave key as nil if none
],
send_channels: %w(#somechannel #otherchannel),
notice: false # Send notices instead of privmsgs
}
# YOU MAY NOT EDIT BELOW #
IRC_COLORS = {
bold: "\\x02",
blue: "\\x0302",
green: "\\x0303",
red: "\\x0304",
reset: "\\x03"
}
STATE_COLORS = {
successful: IRC_COLORS[:green],
failed: IRC_COLORS[:red],
unknown: IRC_COLORS[:blue]
}
class Client
@socket = nil
def initialize(hostname: raise(ArgumentError), port: raise(ArgumentError), nickname: raise(ArgumentError), username: nil, password: nil)
# noinspection RubyResolve
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
@socket.connect(Socket.pack_sockaddr_in(port, hostname))
unless password.nil?
self.send_line("PASS #{password}")
end
self.send_line("NICK #{nickname}")
self.send_line("USER #{username.nil? ? nickname : username} localhost #{hostname} #{nickname}")
self.wait_for([375, 422])
end
def wait_for(codes)
while true
split = self.recv_line.split(' ')
break if split.size > 1 && self.is_numeric(split[1]) && codes.include?(Integer(split[1]))
end
end
def recv_line
line = ''
while line.length < 1 || line[-1] != "\\n"
line += @socket.read(1)
end
line
end
def join(target, key: nil)
self.send_line("JOIN #{target}#{key == nil ? '' : ' ' + key}")
self.wait_for([331, 332, 353, 366, 461, 474, 473, 475, 471, 476, 403, 405])
end
def privmsg(target, message)
self.send_line("PRIVMSG #{target} :#{message}")
end
def notice(target, message)
self.send_line("NOTICE #{target} :#{message}")
end
def quit(message: '')
self.send_line("QUIT#{message == '' ? message : ' ' + message}")
sleep(1)
end
def send_line(line)
return unless line.is_a?(String)
line += "\\r\\n"
@socket.write(line)
end
def close
@socket.close
end
def is_numeric(thing)
true if Integer(thing) rescue false
end
end
def get_state_color(state)
state = state.downcase.to_sym
STATE_COLORS.include?(state) ? STATE_COLORS[state] : ''
end
def shorten_link(link)
open("http://is.gd/create.php?format=simple&url=#{URI::encode(link)}").read.sub(/\\r?\\n/, '')
end
if ARGV.size < 2
puts 'You have set up the IRC notification script wrong.'
exit 1
end
RESULTS_URL = ARGV[0]
API_URL = RESULTS_URL.sub('/browse/', '/rest/api/latest/result/')
PLAN_KEY = ARGV[1]
BUILD_NUMBER = API_URL.split('-')[-1]
BUILD_URL = RESULTS_URL.split('/')[0..-2].join('/') + "/#{PLAN_KEY}-#{BUILD_NUMBER}"
SHORTENED_BUILD_URL = shorten_link(BUILD_URL)
info_url = API_URL.split('/')[0..-2].join('/') + "/#{PLAN_KEY}-#{BUILD_NUMBER}?expand=stages"
j = JSON.parse(open(info_url, 'Accept' => 'application/json').read)
exit 1 unless j.include?('stages')
stages = j['stages']
size = stages['size'] - 1
exit 1 if size < 1
messages = [
"Plan #{IRC_COLORS[:bold]}#{j['planName']}#{IRC_COLORS[:bold]} build results – #{SHORTENED_BUILD_URL}"
]
(0..size - 1).each { |i|
stage = stages['stage'][i]
next unless EVENTS.include?(stage['state'].downcase)
sc = get_state_color(stage['state'])
messages.push("Stage #{IRC_COLORS[:bold]}#{stage['name']}#{IRC_COLORS[:bold]} finished with status #{sc}#{stage['state']}#{IRC_COLORS[:reset]}.")
}
c = Client.new(hostname: IRC_INFO[:server], port: IRC_INFO[:port], nickname: IRC_INFO[:nickname], password: IRC_INFO[:password])
IRC_OPTIONS[:join_channels].each { |ch|
c.join(ch.name, key: ch.key)
}
IRC_OPTIONS[:send_channels].each { |ch|
messages.each { |msg|
if IRC_OPTIONS[:notice]
c.notice(ch, msg)
else
c.privmsg(ch, msg)
end
}
}
c.quit(message: 'Bamboo IRC')
c.close
EOF
/usr/local/bin/ruby -e "${RUBY_SCRIPT}" $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment