App-GHGen
view release on metacpan or search on metacpan
to $Config{version} to form the final cache key.
Rationale: Strawberry Perl occasionally re-releases the same Perl version (e.g. 5.40.0)
with a recompiled DLL that changes the XS handshake key but leaves $Config{version}
unchanged. Reading the binary detects any such change without requiring Digest::MD5.
(An earlier Digest::MD5->addfile approach failed on some runners with "Can't use an
undefined value as filehandle reference"; read + unpack avoids that entirely.)
0.06 Fri Jul 17 11:39:03 EDT 2026
[ Bug Fixes ]
- Approved https://github.com/nigelhorne/App-GHGen/pull/6
Missing unescaped $ failed to interpolate variable into double-quoted string
Thanks to https://github.com/chromatic
- Fixed enable_linter_unused having no effect when set to 1 via the non-interactive code
path. The POD Params::Validate block (default => 0) is documentation only; the actual
runtime default was the // 0 on the assignment line (line 286). Changed to // 1.
[ New Features ]
- Added Perl syntax linting step to generated workflows (enable_linter, default: on)
Uses shell: perl {0} so it runs cross-platform without OS-specific branching.
Searches lib/ and bin/, uses do $file with a stub @INC handler for every .pm file,
and covers every matrix cell (all OS Ã Perl version combinations).
scripts/generate_index.pl view on Meta::CPAN
use File::Glob ':glob';
use File::Slurp;
use File::stat;
use IPC::Run3;
use JSON::MaybeXS;
use List::Util;
use POSIX qw(strftime);
use Readonly;
use HTTP::Tiny;
use Time::HiRes qw(sleep);
use URI::Escape qw(uri_escape);
use version;
use WWW::RT::CPAN;
my ($github_user, $github_repo);
if (my $repo = $ENV{GITHUB_REPOSITORY}) {
($github_user, $github_repo) = split m{/}, $repo, 2;
} else {
die 'What repo are you?';
}
scripts/generate_index.pl view on Meta::CPAN
# Now calculate deltas and create JavaScript data points
my @data_points;
my $prev_pct;
foreach my $point (@data_points_with_time) {
my $delta = defined $prev_pct ? sprintf('%.1f', $point->{pct} - $prev_pct) : 0;
$prev_pct = $point->{pct};
my $color = $delta > 0 ? 'green' : $delta < 0 ? 'red' : 'gray';
my $comment = js_escape($point->{comment});
push @data_points, qq{{ x: "$point->{timestamp}", y: $point->{pct}, delta: $delta, url: "$point->{url}", label: "$point->{timestamp}", pointBackgroundColor: "$color", comment: "$comment" }};
}
my $js_data = join(",\n", @data_points);
if(scalar(@data_points)) {
push @html, <<'HTML';
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1em;">
<div>
<h2>Coverage Trend</h2>
scripts/generate_index.pl view on Meta::CPAN
'</p>';
} else {
push @html, "<p>No issues active on <a href=\"$rt_url\">RT</a></p>";
}
}
# -------------------------------
# CPAN Testers failing reports table
# -------------------------------
my $dist_name = $config{github_repo};
my $cpan_api = "https://api.cpantesters.org/v3/summary/" . uri_escape($dist_name);
my $http = HTTP::Tiny->new(agent => 'cpan-coverage-html/1.0', timeout => 15);
my $retry = 0;
my $success = 0;
my $res;
# Try a number of times because the cpantesters website can get overloaded
while($retry < $config{max_retry}) {
scripts/generate_index.pl view on Meta::CPAN
# Safe git command execution
sub run_git {
my @cmd = @_;
my ($out, $err);
run3 ['git', @cmd], \undef, \$out, \$err;
return unless $? == 0;
chomp $out;
return $out;
}
sub js_escape {
my $str = $_[0];
$str =~ s/\\/\\\\/g;
$str =~ s/"/\\"/g;
$str =~ s/\n/\\n/g;
return $str;
}
sub fetch_reports_by_grades {
my ($dist, $version, @grades) = @_;
my %seen;
my @reports;
for my $grade (@grades) {
my $url = 'https://api.cpantesters.org/v3/summary/'
. uri_escape($dist)
. '/' . uri_escape($version)
. "?grade=$grade";
my $res = $http->get($url);
next unless $res->{success};
my $arr = eval { decode_json($res->{content}) };
next unless ref $arr eq 'ARRAY';
for my $r (@$arr) {
my $key = make_key($r);
#!/usr/bin/env perl
# Regression test for https://github.com/nigelhorne/App-GHGen/pull/6
#
# Bug: "\$savings->{cost}/month" in bin/ghgen escaped the $ so the hash
# dereference was never interpolated. The output read literally
# "$savings->{cost}/month" instead of e.g. "$0.60/month".
#
# Fix: "\$$savings->{cost}/month" â \$ gives a literal $ then
# $savings->{cost} is interpolated normally.
use v5.36;
use Test::Most;
use Path::Tiny;
use IPC::Run3;
( run in 0.987 second using v1.01-cache-2.11-cpan-a5162978ef8 )