我们公司使用Skype进行通讯,我希望能够在Jenkins构建失败(以及恢复时)向Skype聊天室发送警报。
我怎样才能做到这一点?
我已经使用Skype公共API完成了此操作
我所做的是编写一个Perl脚本,该脚本使用SkypeAPI
CPAN模块来处理与Skype的通信。这有点笨拙,因为脚本需要在运行Skype的桌面上运行。我在始终可以在自己的桌面上运行它,但这确实意味着该机器人在我们团队的其他成员看来都是“我”。
最终结果是惊人的-每当詹金斯人构建改变状态时,该机器人就会通过键入
alert将消息发送到任何已注册兴趣的Skype聊天。此外,任何开发人员都可以通过键入
jenkins来查看和共享最新的构建状态
现在,SkypeAPI模块非常基础。它在listen()方法中具有消息循环,该消息循环检查来自Skype客户端的新事件,如果没有,则休眠一会儿。
我希望我的脚本进入此循环,以便我的机器人可以定期检查Jenkins RSS
feed,因此在用ActiveState软件包管理器安装后,我对SkypeAPI.pm进行了以下修改:
我声明了新属性“ idler”以及现有属性…
__PACKAGE__->mk_accessors(
qw/api handler_list stop_listen idler/
);
我添加了一种方法来设置模块将调用而不是休眠的“ idler”回调
sub register_idler {
my $self = shift;
my $ref_sub = shift;
$self->idler($ref_sub);
}
最后,我修改了消息循环以调用惰轮(如果已设置)
sub listen {
my $self = shift;
my $idler=$self->idler();
$self->stop_listen(0);
while (!$self->stop_listen) {
my $message;
{
lock @message_list;
$message = shift @message_list;
}
if (not defined $message) {
if ($idler)
{
$self->idler->($self);
}
else
{
sleep 0.1;
}
next;
}
for my $id (sort keys %{$self->handler_list}) {
$self->handler_list->{$id}->($self, $message);
}
}
}
现在该模块的功能更加强大,只需要编写一个脚本来充当机器人即可。这是我的-我对原始文件进行了一些编辑,因为它包含其他不相关的功能,但它应该为您提供一个起点。
所有从属模块都可以与ActiveState软件包管理器一起安装。
use strict;
use SkypeAPI;
use LWP::Simple;
use Data::Dumper;
use dirtyRSS;
use Time::Local 'timegm';
use Math::Round;
use Storable;
#CHANGE THIS - where to get jenkins status from
my $jenkinsRss='http://username:password@jenkins.example.com/rssLatest';
my %commands=(
'jenkins' =>\&cmdJenkins,
'alert' =>\&cmdAlert,
'noalert' =>\&cmdNoAlert,
'help' =>\&cmdHelp,
);
my $helpMessage=<<HELP;
Who asked for help? Here's all the other special commands I know...
*jenkins - show status of our platform tests
*alert - add this room to get automatic notification of build status
*noalert - cancel notifcations
*help - displays this message
HELP
#status for jenkins tracking
my %builds;
my $lastJenkinsCheck=0;
my $alertRoomsFile='alert.rooms';
my $alertRooms={};
#store jenkins state
checkJenkins();
#because that was our first fetch, we'll have flagged everything as changed
#but it hasn't really, so we reset those flags
resetJenkinsChangeFlags();
#remember rooms we're supposed to alert
loadAlertRooms();
#attach to skype and enter message loop
my $skype = SkypeAPI->new();
my $attached=$skype->attach();
$skype->register_handler(\&onEvent);
$skype->register_idler(\&onIdle);
$skype->listen();
exit;
#here are the command handlers
sub cmdJenkins
{
my ($chatId, $args)=@_;
my $message="";
foreach my $build (keys(%builds))
{
$message.=formatBuildMessage($build)."\n";
#reset changed flag - we've just show the status
$builds{$build}->{'changed'}=0;
}
chatmessage($chatId, $message);
}
sub cmdAlert
{
my ($chatId, $args)=@_;
addChatroomToAlerts($chatId,1);
}
sub cmdNoAlert
{
my ($chatId, $args)=@_;
addChatroomToAlerts($chatId,0);
}
sub cmdHelp
{
my ($chatId, $args)=@_;
chatmessage($chatId, $helpMessage);
}
#simple helper to transmit a message to a specific chatroom
sub chatmessage
{
my ($chatId, $message)=@_;
my $commandstr="CHATMESSAGE $chatId $message";
my $command = $skype->create_command( { string => $commandstr} );
$skype->send_command($command);
}
#refreshes our copy of jenkins state, and will flag any builds
#which have changed state since the last check
sub checkJenkins{
my $xml = get($jenkinsRss);
my $tree = parse($xml);
my $items=$tree->{'channel'}->[0]->{'item'};
foreach my $item (@{$items})
{
my $title=$item->{'title'};
my $link=$item->{'link'};
my $built=$item->{'lastbuilddate'};
#print Dumper($item);
if ($title=~m/^(.*?) #(\d+)\s*(.*)$/)
{
my $build=$1;
my $buildnumber=$2;
my $status=$3;
#print "$build\n$buildnumber\n$status\n$link\n$built\n\n";
#build in progress, ignore
if (!exists($builds{$build}))
{
$builds{$build}={};
$builds{$build}->{'status'}='';
$builds{$build}->{'changed'}=0;
}
$builds{$build}->{'name'}=$build;
if ($status eq '(?)')
{
$builds{$build}->{'in_progress'}=1;
next; #don't update until complete
}
else
{
$builds{$build}->{'in_progress'}=0;
}
#is this status different to last status?
if ($builds{$build}->{'status'} ne $status)
{
$builds{$build}->{'changed'}=1;
}
$builds{$build}->{'status'}=$status;
$builds{$build}->{'build_number'}=$buildnumber;
$builds{$build}->{'link'}=$link;
$builds{$build}->{'built'}=$built;
}
}
#print Dumper(\%builds);
}
#generates a string suitable for displaying build status in skype
sub formatBuildMessage
{
my ($build)=@_;
my $status=$builds{$build}->{'status'};
my $smiley=":)";
if ($status=~m/broken/)
{
$smiley="(devil)";
}
elsif ($status=~m/\?/)
{
#this means the build is being retested, we should skip it
$smiley=":|";
}
my $message='';
if ($builds{$build}->{'in_progress'})
{
$message=":| $build - rebuild in progress..."
}
else
{
my ($y,$mon,$d,$h,$m,$s) = $builds{$build}->{'built'} =~ m/(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z/;
my $time = timegm($s,$m,$h,$d,$mon-1,$y);
my $age=time()-$time;
my $mins=round($age/60);
my $hrs=round($age/3600);
my $days=round($age/86400);
my $niceage;
if ($mins<=2)
{
$niceage="a few moments ago";
}
elsif ($mins<120)
{
$niceage="$mins minutes ago";
}
elsif ($hrs<48)
{
$niceage="$hrs hours ago";
}
else
{
$niceage="$days days ago";
}
$message="$smiley $build last built $niceage $status";
}
return $message;
}
#forget any changes we've flagged
sub resetJenkinsChangeFlags
{
foreach my $build (keys(%builds))
{
$builds{$build}->{'changed'}=0;
}
}
#checks for builds which have changed state. Can be called
#often, it will only kick in if 60 seconds have elapsed since
#last check
sub checkForJenkinsChanges
{
my $now=time();
if (($now-$lastJenkinsCheck) < 60)
{
#no need, we fetched it recently
return;
}
checkJenkins();
my $message='';
foreach my $build (keys(%builds))
{
if ($builds{$build}->{'changed'})
{
$builds{$build}->{'changed'}=0;
$message.=formatBuildMessage($build)."\n";
}
}
if (length($message))
{
foreach my $chatId (keys(%$alertRooms))
{
chatmessage($chatId, $message);
}
}
$lastJenkinsCheck=$now;
}
#adds or removes a room from the alerts
sub addChatroomToAlerts
{
my($chatId, $add)=@_;
if ($add)
{
if (exists($alertRooms->{$chatId}))
{
chatmessage($chatId, "/me says this room is already getting alerts");
}
else
{
$alertRooms->{$chatId}=1;
chatmessage($chatId, "/me added this chatroom to jenkins alerts");
}
}
else
{
delete($alertRooms->{$chatId});
chatmessage($chatId, "/me removed this chatroom from jenkins alerts");
}
store $alertRooms, $alertRoomsFile;
}
sub loadAlertRooms
{
if (-e $alertRoomsFile)
{
$alertRooms = retrieve( $alertRoomsFile);
}
}
# Skype event handler
sub onEvent {
my $skype = shift;
my $msg = shift;
#my $command = $skype->create_command( { string => "GET USERSTATUS"} );
#print $skype->send_command($command) , "\n";
#print "handler: $msg\n";
#an inbound chat message is either
#MESSAGE 13021257 STATUS RECEIVED (from others)
#MESSAGE 13021257 STATUS SENT (from us)
if ($msg =~ m/MESSAGE (\d+) STATUS (SEND|RECEIVED)/)
{
my $msgId=$1;
#get message body
my $commandstr="GET CHATMESSAGE $msgId BODY";
my $command = $skype->create_command( { string => $commandstr} );
my $output=$skype->send_command($command);
#if its a message for us...
if ($output =~ m/MESSAGE $msgId BODY \*([^\s]*)\s*(.*)/i)
{
my $botcmd=$1;
my $botargs=$2;
$commandstr="GET CHATMESSAGE $msgId CHATNAME";
$command = $skype->create_command( { string => $commandstr} );
$output=$skype->send_command($command);
if ($output =~ m/MESSAGE $msgId CHATNAME (.*)/)
{
my $chatId=$1;
if (exists($commands{$botcmd}))
{
$commands{$botcmd}->($chatId, $botargs);
}
else
{
chatmessage($chatId, "/me suggests trying *help as the robot didn't understand *$botcmd");
}
}
}
}
}
#skype idle handler
#Note - SkypeAPI.pm was modified to support this
sub onIdle {
my $skype = shift;
checkForJenkinsChanges();
sleep 0.1;
}
如果已将其另存为robot.pl,则只需打开一个控制台窗口即可perl robot.pl
运行它。Skype会询问您是否应允许perl.exe与之通信,一旦确认,就可以了!
进入团队聊天室并键入*jenkins
最新版本的摘要,然后注册会议室以通过以下方式通知版本更改*alert
完美的:)
下面是给我带来麻烦的文件: 我试图通过路由将新的和传递到我的“feed”组件中。但我收到一条错误消息: 我知道为什么会发生这种情况,但不知道如何将状态传递给我的“feed”组件。在过去的5个小时里,我一直在试图解决这个问题,我变得非常绝望! 请救命!谢谢 下面的答案很有帮助,我感谢athors,但他们不是做到这一点的最简单的方法。在我的例子中,最好的方法是这样的:当您更改路线时,只需向其附加一条消
问题内容: 以下“执行系统Groovy脚本”构建任务将更新构建描述,以添加一个按钮,该按钮将提交另一个已参数化的Jenkins作业: 但是,单击“继续”按钮后,该请求将返回400 Bad Request。看起来是因为构建参数未正确传递(如果我从另一个作业中删除构建参数并且不传递参数,则一切正常)。 我不确定问题是否是由于引用错误或通过构建参数发送方式引起的。 问题答案: 您需要使用JSON。请参阅
问题内容: 是否可以通过Jdbc模板在SQL查询中生成任意“ in()”列表: 例: “从t中选择*,其中c在(#)中”,但是’#’可以是仅在运行时才知道的任意值列表。 问题答案: 是的,如果你使用使用命名参数,则可能在Spring中。List参数可以设置为: 在这种情况下,当使用s 替换命名参数时,Spring会根据实际列表的大小在内部使用所需数量的占位符创建SQL查询。
我的自动化测试有问题,我的测试通过Eclipse运行没有问题。 但是当我想在Jenkins上运行这个测试时,它总是在同一行(在同一个选择器上)失败。 在端口21173上运行TestSuite启动ChromeDriver2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4)仅允许本地连接。测试运行: 1,失败: 1,错误: 0,跳过: 0,时间流
Display a notification message globally. Basic The simplest usage that close the notification box after 4.5s. <w class="button-container"> <button ref="notification-basic" class="btn btn-primary">Op
当我在PHP中使用file\u get\u contents函数来更新我的电报机器人时,我知道如何获取第一个聊天ID或文本,但这个页面不仅仅适用于一个用户 它获取在我的机器人中键入的第一个用户聊天ID。当我对他的短信做出反应时,我会将我的消息发送给使用我的机器人的最新用户。。。我该怎么做?