Script-fu:如何创建641个请求跟踪器工单
我大部分时间都在纽约Perl黑客马拉松(感谢彭博!)中编写Perl 6相关代码。在Will “Coke” Coleda的带领下,我们的一个任务是找到Perl 6测试套件中缺少请求跟踪器(RT)工单号的跳过/待办指令。
一个典型的跳过/待办指令看起来像这样
#?rakudo todo "doesn't work yet due to copying of arrays"
这告诉Rakudo跳过下面的测试块。对于每个跳过/待办指令,都需要创建一个新的RT工单,并将工单号添加到测试文件中相应的跳过指令行,如下所示
#?rakudo todo "doesn't work yet due to copying of arrays RT #99999"
这使得Rakudo团队更容易识别Rakudo中剩余的bug或缺失的功能。
我克隆了Perl 6测试套件,roast,并在完成单个工单的工作流程后,我开始想知道还有多少其他跳过/待办指令缺少RT工单号。为了找出答案,我使用了一些小的grep
魔法
$ grep -rlP '#?rakudo.+?(?:skip|todo)(?:(?!RT).{2})+$' ./ | wc -l
这告诉grep在当前目录中递归搜索文件,并对于每个文件,如果Perl风格的正则表达式与文件中的文本匹配,则打印文件名。正则表达式匹配Rakudo中尚未有RT引用的跳过/待办指令。然后,grep的输出被传递到wc
以计算文件数量。结果发现有236个文件受到影响,这种方法甚至没有计算文件内部的出现次数。即使为每个文件创建工单、更新文件、提交更改和发布拉取请求需要5分钟,那也是20小时的工作。当需要将这项工作分配给多个人时,事情变得更加复杂。这时,我的蜘蛛感应开始作祟……你能说“自动化”吗?
用机器创建RT工单“像机器一样”
我写了一个快速脚本再次查找所有的跳过/待办指令,但这次我会捕获文件名、行号和描述
use strict;
use warnings;
scan_directory('.');
sub scan_directory
{
my ($dir) = @_;
opendir(my $dh, "$dir") or die $!;
while (readdir $dh)
{
my $newpath = "$dir/$_";
next if $newpath !~ qr/^\.\/S/ || -l $newpath;
if (-d $newpath && $newpath !~ /\.$/)
{
scan_directory($newpath);
}
elsif (-f $newpath)
{
open my $file, '<', $newpath or die "failed to open $newpath $!\n";
my $line_num = 1;·
while (<$file>)
{
chomp;
if (/^#\?rakudo.+?(?:skip|todo)((?:(?!RT).)+)$/)
{
my $subject = sprintf "Roast rakudo skip/todo test:%s line:%s reason:%s",
$newpath, $line_num, $1;
$subject =~ s/"//g;
my $response = `rt create -t ticket set subject="$subject" queue=perl6 priority=0`;
if ($response =~ /([0-9]+)/)
{
printf "%s RT#:%s\n", $subject, $1;
}
else
{
die "Failed to capture ticket # for $subject response: $response";
}
}
$line_num++;
}
close $file;
}
}
}
这个脚本相当简单:它是一个递归目录扫描器,用于扫描文件中的Rakudo跳过/待办块。该脚本使用以下带有反引号的代码行执行rt
命令行程序,在Perl 6队列中创建一个工单,并捕获响应
my $response = `rt create -t ticket set subject="$subject" queue=perl6 priority=0`;
脚本从$response
中提取RT工单号,并打印包含文件名、行号、描述和RT工单号的行。我将这些输出保存在一个单独的文件中
.
关于配置RT CLI的简要说明
配置和使用RT命令行客户端很简单,但了解如何操作可能很困难 - 大多数我看到的资料都过时了,RT CPAN命名空间有太多的“烧毁的尸体”,连《Mad Max》也会感到自在。要使用命令行客户端,首先安装RT::Client::CLI
$ cpan RT::Client::CLI
然后登录到RT Perl 网站,转到用户 首选项 并设置CLI密码。最后,在你的主目录中创建文件.rtrc
。该文件应包含
server https://rt.perl.org/
user rt_username
passwd rt_cli_password
将rt_username
替换为RT屏幕顶部显示的名称。对我而言,是我的电子邮件地址。也将rt_cli_password
替换为你刚刚设置的CLI密码。或者,你也可以使用以下环境变量而不是配置文件:RTSERVER、RTUSER和RTPASSWD。
这就完成了,RT现在已配置!尝试一些命令。RT Essentials书籍的第4章也很有用。
更新roast
既然我已经有了所需的RT票号,我需要回到roast中的单元测试文件,将它们添加到跳过/待办指令中。我也为这个过程编写了脚本。
use strict;
use warnings;
open my $tickets, '<', './tickets';
while (my $line = <$tickets>)
{
chomp $line;
if (my ($filename, $line_num, $reason, $ticket_num) = $line =~ /:(.+?) .+?:(.+?) .+?:(.+?) .+?:(.+?)$/)
{
open my $file, '<', $filename or die "failed to open $filename $!\n";
my $counter = 1;
my @lines;
while (my $line = <$file>)
{
if ($counter == $line_num)
{
chomp $line;
$line =~ s/('|")\s*$/ RT #$ticket_num$1\n/;
}
push @lines, $line;
$counter++;
}
close $file;
open my $output_file, '>', $filename or die "failed to open $filename $!\n";
for (@lines)
{
print $output_file $_;
}
close $output_file;
}
else
{
die "failed to match $line!\n";
}
}
这需要几次尝试才能正确完成。一开始我想尝试使用open
和一个使用+<
的惊人的读写文件句柄,但这似乎比它所值得的麻烦要多。另一个挑战是将RT票号插入到该行的引号字符串内,而不是外面。所以这
#?rakudo todo "doesn't work yet due to copying of arrays"
变成了这样
#?rakudo todo "doesn't work yet due to copying of arrays RT #124652"
这里的挑战在于不同的描述使用不同的分隔符来捕获描述,无论是单引号还是双引号。在脚本中,这一行处理了这个问题
$line =~ s/('|")\s*$/ RT #$ticket_num$1\n/;
这是一个替换正则表达式,它捕获行上最后的引号分隔符,并用RT票号加上捕获的分隔符($1
)来替换它。它成功了!
总结
最终,我在roast中的236个测试文件中创建了641个票,大约花费了2小时的工作时间。其中大部分时间花在尝试配置RT命令行客户端上。提出数百个票时需要记住的一件事是电子邮件通知。幸运的是,Robert Spier拦截了邮件发送(感谢Robert!),但如果有可能避免在提出票时创建数百个通知,那就太好了。如果有办法,我很乐意知道如何。
感谢Will “Coke” Coleda、Tobias Leich(FROGGS)和Christian Bartolomäus(usev6)审阅了这个pull request并完成了合并工作。如果您有兴趣支持Perl 6,Rakudo团队有一个页面解释了如何贡献。我还建议您查看Perl 6社区页面。
如果您在纽约或北美东北部,我将于6月6日在Miniconf黑客马拉松上,带领一个团队将Perl 5模块转换为Perl 6。希望在那里见到每个人!
这篇文章最初发布在PerlTricks.com。
标签
反馈
这篇文章有什么问题吗?请在GitHub上打开一个issue或pull request来帮助我们。