3
# pr-removes-fixed-skips - if PR says "Fixes: #123", no skips should mention 123
5
package Podman::CI::PrRemovesFixedSkips;
10
# Grumble. CI system doesn't have 'open'
11
binmode STDIN, ':utf8';
12
binmode STDOUT, ':utf8';
17
(our $ME = $0) =~ s|.*/||;
20
###############################################################################
21
# BEGIN boilerplate args checking, usage messages
27
$ME reads a GitHub PR message, looks for
28
Fixed/Resolved/Closed issue IDs, then greps for test files
29
containing 'Skip' instructions or FIXME comments referencing
30
those IDs. If we find any, we abort with a loud and hopefully
33
$ME is intended to run from Cirrus CI.
37
--help display this message
38
--version display program name and version
44
# Command-line options. Note that this operates directly on @ARGV !
52
version => sub { print "$ME version $VERSION\n"; exit 0 },
53
) or die "Try `$ME --help' for help\n";
56
# END boilerplate args checking, usage messages
57
###############################################################################
59
############################## CODE BEGINS HERE ###############################
61
# The term is "modulino".
62
__PACKAGE__->main() unless caller();
66
# Note that we operate directly on @ARGV, not on function parameters.
67
# This is deliberate: it's because Getopt::Long only operates on @ARGV
68
# and there's no clean way to make it use @_.
69
handle_opts(); # will set package globals
71
die "$ME: This script takes no arguments; try $ME --help\n" if @ARGV;
73
# Check commit messages from both github and git; they often differ
74
my @issues = fixed_issues(cirrus_change_message(), git_commit_messages())
77
my @found = unremoved_skips(@issues)
80
# Found unremoved skips. Fail loudly.
81
my $issues = "issue #$issues[0]";
83
$issues = "issues #" . join ", #", @issues;
86
warn "$ME: Your PR claims to resolve $issues\n";
87
warn " ...but does not remove associated Skips/FIXMEs:\n";
89
warn " $_\n" for @found;
92
Please do not leave Skips or FIXMEs for closed issues.
94
If an issue is truly fixed, please remove all Skips referencing it.
96
If an issue is only PARTIALLY fixed, please file a new issue for the
97
remaining problem, and update remaining Skips to point to that issue.
99
And if the issue is fixed but the Skip needs to remain for other
100
reasons, again, please update the Skip message accordingly.
106
# unremoved_skips # Returns list of <path>:<lineno>:<skip string> matches
109
my $issues = join('|', @_);
111
my $re = "(^\\s\+skip|fixme).*#($issues)[^0-9]";
112
# FIXME FIXME FIXME: use File::Find instead of enumerating directories
113
# (the important thing here is to exclude vendor)
114
my @grep = ('grep', '-E', '-rin', $re, "test", "cmd", "libpod", "pkg");
117
open my $grep_fh, '-|', @grep
118
or die "$ME: Could not fork: $!\n";
119
while (my $line = <$grep_fh>) {
122
# e.g., test/system/030-run.bats:809: skip "FIXME: #12345 ..."
123
$line =~ m!^(\S+):\d+:\s!
124
or die "$ME: Internal error: output from grep does not match <path>:<lineno>:<space>: '$line'";
127
# Any .go or .bats file, or the apply-podman-deltas script
128
if ($path =~ /\.(go|bats)$/ || $path =~ m!/apply-podman-deltas$!) {
132
# Anything else is probably a backup file, or something else
133
# we don't care about. (We won't see these in CI, but might
134
# in a user devel environment)
136
print "[ ignoring: $line ]\n";
145
# fixed_issues # Parses change message, looks for Fixes/Closes/Resolves
151
# https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
154
while ($msg =~ /\b(Fix|Clos|Resolv)[esd]*[:\s]+\#(\d+)/gis) {
155
# Skip dups: we're probably checking both github and git messages
157
unless grep { $_ eq $2 } @issues;
164
###########################
165
# cirrus_change_message # this is the one from *GitHub*, not *git*
166
###########################
167
sub cirrus_change_message {
168
my $change_message = $ENV{CIRRUS_CHANGE_MESSAGE}
170
# OK for it to be unset if we're not running CI on a PR
171
return if ! $ENV{CIRRUS_PR};
172
# But if we _are_ running on a PR, something went badly wrong.
173
die "$ME: \$CIRRUS_CHANGE_MESSAGE is undefined\n";
176
return $change_message;
179
#########################
180
# git_commit_messages # the ones from the *git history*
181
#########################
182
sub git_commit_messages {
183
# Probably the same as HEAD, but use Cirrus-defined value if available
184
my $head = $ENV{CIRRUS_CHANGE_IN_REPO} || 'HEAD';
186
# Base of this PR. Here we absolutely rely on cirrus.
187
return if ! $ENV{DEST_BRANCH};
188
chomp(my $base = qx{git merge-base $ENV{DEST_BRANCH} $head});
190
qx{git log --format=%B $base..$head};