App-GHGen
view release on metacpan or search on metacpan
scripts/generate_index.pl view on Meta::CPAN
if (my $repo = $ENV{GITHUB_REPOSITORY}) {
($github_user, $github_repo) = split m{/}, $repo, 2;
} else {
die 'What repo are you?';
}
my $package_name = $github_repo;
$package_name =~ s/\-/::/g;
Readonly my %config => (
github_user => 'nigelhorne',
github_repo => $github_repo,
package_name => $package_name,
low_threshold => 70,
med_threshold => 90,
max_points => 10, # Only display the last 10 commits in the coverage trend graph
cover_db => 'cover_db/cover.json',
output => 'cover_html/index.html',
max_retry => 3,
min_locale_samples => 3,
);
# -------------------------------
# Dependency correlation analysis
# -------------------------------
my $MAX_REPORTS_PER_GRADE = 20; # safety rail
my $ENABLE_DEP_ANALYSIS = 1;
# Read and decode coverage data
my $data = eval { decode_json(read_file($config{cover_db})) };
my $coverage_pct = 0;
my $badge_color = 'red';
if(my $total_info = $data->{summary}{Total}) {
$coverage_pct = int($total_info->{total}{percentage} // 0);
$badge_color = $coverage_pct > $config{med_threshold} ? 'brightgreen' : $coverage_pct > $config{low_threshold} ? 'yellow' : 'red';
}
Readonly my $coverage_badge_url => "https://img.shields.io/badge/coverage-${coverage_pct}%25-${badge_color}";
# Start HTML
my @html; # build in array, join later
push @html, <<"HTML";
<!DOCTYPE html>
<html>
<head>
<title>$config{package_name} Coverage Report</title>
<style>
body { font-family: sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.low { background-color: #fdd; }
.med { background-color: #ffd; }
.high { background-color: #dfd; }
.badges img { margin-right: 10px; }
.disabled-icon {
opacity: 0.4;
cursor: default;
}
.icon-link {
text-decoration: none;
}
.icon-link:hover {
opacity: 0.7;
cursor: pointer;
}
.coverage-badge {
padding: 2px 6px;
border-radius: 4px;
font-weight: bold;
color: white;
font-size: 0.9em;
}
.badge-good { background-color: #4CAF50; }
.badge-warn { background-color: #FFC107; }
.badge-bad { background-color: #F44336; }
.summary-row {
font-weight: bold;
background-color: #f0f0f0;
}
td.positive { color: green; font-weight: bold; }
td.negative { color: red; font-weight: bold; }
td.neutral { color: gray; }
/* Show cursor points on the headers to show that they are clickable */
th { background-color: #f2f2f2; cursor: pointer; }
th.sortable {
cursor: pointer;
user-select: none;
white-space: nowrap;
}
th .arrow {
color: #aaa; /* dimmed for inactive */
font-weight: normal;
}
th .arrow.active {
color: #000; /* dark for active */
font-weight: bold;
}
.sparkline {
display: inline-block;
vertical-align: middle;
}
tr.cpan-fail td {
background-color: #fdd;
}
tr.cpan-unknown td {
background-color: #eee;
color: #666;
}
tr.cpan-na td {
background-color: #ffffde;
color: #666;
}
.new-failure {
background: #c00;
color: #fff;
font-weight: bold;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.85em;
}
.notice {
padding: 8px 12px;
margin: 10px 0;
border-radius: 4px;
font-size: 0.95em;
}
.notice strong {
font-weight: bold;
}
.notice.perl-version-cliff {
background-color: #fff3cd; /* soft amber */
border: 1px solid #ffeeba;
color: #856404;
}
.notice.perl-version-cliff a {
color: #533f03;
text-decoration: underline;
}
.notice.perl-version-cliff a:hover {
text-decoration: none;
}
.notice.locale-cliff {
border-left: 4px solid #d97706;
background: #fffbeb;
padding: 0.5em 1em;
}
( run in 1.175 second using v1.01-cache-2.11-cpan-140bd7fdf52 )