App-GHGen

 view release on metacpan or  search on metacpan

bin/ghgen  view on Meta::CPAN

		}

		my @issues = analyze_workflow($workflow, $file->basename);

		if (@issues) {
			# Filter to auto-fixable issues if in fix mode
			my @fixable = $opts{fix} ? grep { can_auto_fix($_) } @issues : @issues;

			if ($opts{fix} && @fixable) {
				say "  " . colored(['yellow'], "âš™ ") . "Applying " . scalar(@fixable) . " fix(es)...";

				my $fixes = fix_workflow($file, \@fixable);
				$total_fixes += $fixes;

				if ($fixes > 0) {
					say "  " . colored(['green'], "✓ ") . "Applied $fixes fix(es)";
				} else {
					say "  " . colored(['yellow'], "âš  ") . "Could not apply some fixes automatically";
				}
			} else {
				# Just report issues
				for my $issue (@issues) {
					my $icon = can_auto_fix($issue) ? "⚠" : "ℹ";
					say "  " . colored(['yellow'], "$icon ") . $issue->{message};
					if ($issue->{fix} && !$opts{fix} && !$opts{estimate}) {
						say colored(['cyan'], "	 💡 Fix:");
						for my $line (split /\n/, $issue->{fix}) {
							say "	 " . $line;
						}
					}
				}
			}

			push @all_issues, map { { file => $file->basename, %$_ } } @issues;
		} else {
			say "  " . colored(['green'], "✓ No issues found");
		}
		say '';
	}

	# Summary
	say colored(['bold cyan'], "=" x 50);
	say colored(['bold'], "Summary:");
	say "  Workflows analyzed: $total_workflows";
	say "  Total issues found: " . scalar(@all_issues);

	if ($opts{fix}) {
		say "  Fixes applied: " . colored(['green'], $total_fixes);
	}

	# Cost savings estimate
	if ($opts{estimate} && @all_issues) {
		say '';
		my $savings = estimate_savings(\@all_issues, \@workflow_files);

		if ($savings->{minutes} > 0) {
			say colored(['bold'], "💰 Potential Savings:");
			say '  With recommended changes: ' . colored(['green'], ($current_usage->{total_minutes} - $savings->{minutes})) .
				" CI minutes/month";
			say "  Reduction: " . colored(['green'], "-$savings->{minutes} minutes") .
				" (" . colored(['green'], "$savings->{percentage}%") . ")";
			say "  Cost savings: " . colored(['green'], "\$savings->{cost}/month") .
				" (for private repos)";

			if (@{$savings->{details}}) {
				say '';
				say "  Breakdown:";
				for my $detail (@{$savings->{details}}) {
					say "	• $detail->{description}: ~$detail->{minutes} min/month";
				}
			}
		}
	}

	if (@all_issues && !$opts{fix}) {
		say '';
		say colored(['bold yellow'], "Recommendations:");
		my %by_type;
		push @{$by_type{$_->{type}}}, $_ for @all_issues;

		for my $type (sort keys %by_type) {
			my $count = scalar @{$by_type{$type}};
			my $fixable = grep { can_auto_fix($_) } @{$by_type{$type}};
			my $suffix = $fixable > 0 ? " ($fixable auto-fixable)" : '';
			say "  • " . colored(['yellow'], "$type") . ": $count workflow(s) affected$suffix";
		}

		say '';
		say colored(['cyan'], "💡 Tip: ") .  "Run " . colored(['bold'], "ghgen analyze --fix") .
			" to automatically apply fixes";

		if (!$opts{estimate}) {
			say colored(['cyan'], "💡 Tip: ") . "Run " . colored(['bold'], "ghgen analyze --estimate") .
				" to see potential cost savings";
		}
	}

	exit(@all_issues ? 1 : 0);
}

sub list_types() {
	say colored(['bold cyan'], "Available workflow templates:");
	say '';

	my %types = list_workflow_types();

	for my $type (sort keys %types) {
		say "  " . colored(['green'], sprintf("%-10s", $type)) . " - $types{$type}";
	}

	say '';
	say "Usage: ghgen generate --type=<type> [--output=<file>]";
	say "   or: ghgen generate --interactive";
}

sub interactive_select_type() {
	say colored(['bold cyan'], "GitHub Actions Workflow Generator");
	say colored(['cyan'], "=" x 50);
	say '';
	say "Select a project type:";
	say '';



( run in 2.486 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )