NAME

App::GHGen::Reporter - Generate reports for GitHub integration

SYNOPSIS

use App::GHGen::Reporter qw(generate_github_comment);

my $comment = generate_github_comment(\@issues, \@fixes);

FUNCTIONS

generate_markdown_report($issues, $fixes)

Produce a Markdown-formatted report of workflow issues and applied fixes.

Purpose

Render a structured Markdown document that summarises detected issues grouped by category, includes suggested fixes, and appends an estimated savings section when applicable.

Arguments

$issues (ArrayRef[HashRef], required)

Issues to report. Each must have type, severity, message; an optional fix key renders a collapsible <details> block.

$fixes (ArrayRef, optional, default [])

List of fixes already applied (used only for the summary count).

Returns

A non-empty Markdown string beginning with # GHGen Workflow Analysis.

Side Effects

None. Pure function.

Usage Example

my $md = generate_markdown_report(\@issues, \@fixes);
path('report.md')->spew_utf8($md);

API SPECIFICATION

Input

{
    issues => { type => 'arrayref', required => 1 },
    fixes  => { type => 'arrayref', default  => [] },
}

Output

{ type => 'scalar' }   # Markdown string

FORMAL SPECIFICATION

generate_markdown_report : seq Issue × seq Fix → ℤ*

result begins with "# GHGen Workflow Analysis"
|issues| > 0 ⇒ result contains "## Issues by Category"
|issues| = 0 ⇒ result does not contain "## Issues by Category"
|fixes|  > 0 ⇒ result contains "Fixes applied"
savings.minutes > 0 ⇒ result contains "## 💰 Estimated Savings"

generate_github_comment($issues, $fixes, $options)

Generate a GitHub Pull-Request comment summarising workflow issues.

Purpose

Produce a compact Markdown comment suitable for posting as a PR review comment. Includes a summary table, a collapsible detail block, a how-to-fix section when no fixes were applied, and a potential savings estimate.

Arguments

$issues (ArrayRef[HashRef], required)

Issues to display. Each must have type, severity, message; an optional file key adds a file reference line.

$fixes (ArrayRef, optional, default [])

Fixes already applied (used only for the applied-fix count in the header).

$options (HashRef, optional, default {})

Reserved for future use; currently unused.

Returns

A non-empty Markdown string starting with ## 🔍 GHGen Workflow Analysis.

When $issues is empty, the comment contains the phrase No issues found! and is returned early without a table or details block.

Side Effects

None. Pure function.

Usage Example

my $comment = generate_github_comment(\@issues, \@fixes);
# Post $comment via GitHub API

API SPECIFICATION

Input

{
    issues  => { type => 'arrayref', required => 1 },
    fixes   => { type => 'arrayref', default  => [] },
    options => { type => 'hashref',  default  => {} },
}

Output

{ type => 'scalar' }   # Markdown string

FORMAL SPECIFICATION

generate_github_comment : seq Issue × seq Fix × Options → ℤ*

result begins with "## 🔍 GHGen Workflow Analysis"
|issues| = 0 ⇒ result contains "No issues found!" ∧ early return
|fixes|  > 0 ⇒ result contains "Applied" ∧ fix count
|issues| > 0 ∧ |fixes| = 0 ⇒ result contains "How to Fix"
∃ i ∈ issues: i.file defined ⇒ result contains i.file

estimate_savings($issues)

Estimate CI-minute savings and associated cost reduction from fixing a set of issues.

Purpose

For each performance (caching) or cost (concurrency, triggers) issue, add a fixed minute estimate to the running total and compute the equivalent USD saving at the GitHub private-repo rate of $0.008/minute.

Arguments

$issues (ArrayRef[HashRef], required)

Issue hashes with at least type and message.

Returns

A hash reference:

{
    minutes => Int,   # total estimated minutes saved per month; 0 when no savings
    cost    => Int,   # floor(minutes * 0.008); 0 when no savings
}

Side Effects

None. Pure function.

Usage Example

my $s = estimate_savings(\@issues);
say "Save $s->{minutes} min/month";

API SPECIFICATION

Input

{ issues => { type => 'arrayref', required => 1 } }

Output

{
    type => 'hashref',
    keys => {
        minutes => { type => 'scalar' },
        cost    => { type => 'scalar' },
    },
}

FORMAL SPECIFICATION

estimate_savings : seq Issue → { minutes: ℕ, cost: ℕ }

RATE ≔ 0.008
savings(i) ≔
    i.type = performance ∧ i.message =~ /caching/     → 500
    i.type = cost        ∧ i.message =~ /concurrency/ → 50
    i.type = cost        ∧ i.message =~ /triggers/    → 100
    otherwise                                          → 0

total  ≔ ∑ { savings(i) ∣ i ∈ issues }
result ≔ { minutes ↦ total, cost ↦ floor(total × RATE) }

AUTHOR

Nigel Horne <njh@nigelhorne.com>

https://github.com/nigelhorne

LICENSE

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 81:

Non-ASCII character seen before =encoding in '×'. Assuming UTF-8