App-GHGen
view release on metacpan or search on metacpan
4. Go
5. Ruby
6. Perl
7. Docker
8. Static site (GitHub Pages)
Enter number (1-8):
## Interactive Customization
Customize workflows with guided prompts:
ghgen generate --type=perl --customize
For Perl, you'll be asked:
- **Perl versions to test** - Select from 5.22 through 5.40 (multi-select with defaults)
- **Operating systems** - Ubuntu, macOS, Windows (multi-select)
- **Enable Perl::Critic** - Code quality analysis (yes/no)
- **Enable Devel::Cover** - Test coverage (yes/no)
- **Branch configuration** - Which branches to run on
if ($opts{list}) {
list_types();
return;
}
my $type = $opts{type};
my $config;
# Auto-detect if requested
if ($opts{auto} || (!$type && !$opts{interactive} && !$opts{customize})) {
$type = auto_detect_with_prompt();
return unless $type; # User cancelled
}
# Interactive mode
if ($opts{interactive} && !$type) {
$type = interactive_select_type();
}
unless ($type) {
die colored(['red'], "Error: ") .
print "Enter number (1-" . scalar(@types) . "): ";
chomp(my $choice = <STDIN>);
if ($choice =~ /^\d+$/ && $choice >= 1 && $choice <= @types) {
return $types[$choice - 1];
}
die colored(['red'], "Invalid choice\n");
}
sub auto_detect_with_prompt() {
say colored(['bold cyan'], "Auto-detecting project type...");
say '';
my @detections = detect_project_type();
unless (@detections) {
say colored(['yellow'], "â ") . "Could not auto-detect project type.";
say '';
say "Try one of these options:";
say " ⢠" . colored(['cyan'], "ghgen generate --list") . " - see all available types";
ghgen generate --auto
ghgen generate --type=perl
ghgen generate --type=perl --customize
ghgen generate --type=node --output=custom.yml
ghgen generate --interactive
ghgen generate --list
Options:
--auto, -a Auto-detect project type and prompt for confirmation
--type, -t TYPE Project type (perl, node, python, rust, go, ruby, docker, static)
--customize, -c Interactively customize the workflow
--output, -o FILE Output file (default: .github/workflows/TYPE-ci.yml)
--interactive, -i Interactive mode to select type
--list, -l List available workflow types
--timeout MINUTES Set job timeout-minutes for Perl workflows (default: 30)
=head2 analyze
Analyze existing workflows for issues and optimizations.
lib/App/GHGen.pm view on Meta::CPAN
4. Go
5. Ruby
6. Perl
7. Docker
8. Static site (GitHub Pages)
Enter number (1-8):
=head2 Interactive Customization
Customize workflows with guided prompts:
ghgen generate --type=perl --customize
For Perl, you'll be asked:
=over 4
=item * B<Perl versions to test> - Select from 5.22 through 5.40 (multi-select with defaults)
=item * B<Operating systems> - Ubuntu, macOS, Windows (multi-select)
lib/App/GHGen/Interactive.pm view on Meta::CPAN
package App::GHGen::Interactive;
use v5.36;
use strict;
use warnings;
use Term::ANSIColor qw(colored);
use Exporter 'import';
our @EXPORT_OK = qw(
prompt_yes_no
prompt_choice
prompt_multiselect
prompt_text
customize_workflow
);
our $VERSION = '0.05';
=head1 NAME
App::GHGen::Interactive - Interactive workflow customization
=head1 SYNOPSIS
use App::GHGen::Interactive qw(customize_workflow);
my $config = customize_workflow('perl');
# Returns hash of user choices
=head1 FUNCTIONS
=head2 prompt_yes_no($question, $default)
Prompt for yes/no answer. Default is 'y' or 'n'.
=cut
sub prompt_yes_no($question, $default = 'y') {
my $prompt = $default eq 'y' ? '[Y/n]' : '[y/N]';
print "$question $prompt: ";
chomp(my $answer = <STDIN>);
return 1 if $answer =~ /^y(es)?$/i;
return 0 if $answer =~ /^n(o)?$/i;
return $default eq 'y' ? 1 : 0;
}
=head2 prompt_choice($question, $choices, $default)
Prompt user to select one option from a list.
=cut
sub prompt_choice($question, $choices, $default = 0) {
say $question;
for my $i (0 .. $#$choices) {
my $marker = $i == $default ? colored(['green'], 'â') : ' ';
say " $marker " . ($i + 1) . ". $choices->[$i]";
}
print "\nEnter number [" . ($default + 1) . "]: ";
chomp(my $answer = <STDIN>);
return $default if $answer eq '';
return $answer - 1 if $answer =~ /^\d+$/ && $answer >= 1 && $answer <= @$choices;
return $default;
}
=head2 prompt_multiselect($question, $options, $defaults)
Prompt user to select multiple options. Returns array ref of selected items.
=cut
sub prompt_multiselect($question, $options, $defaults = []) {
say $question;
say colored(['cyan'], "(Enter numbers separated by commas, or 'all')");
my %is_default = map { $_ => 1 } @$defaults;
for my $i (0 .. $#$options) {
my $marker = $is_default{$options->[$i]} ? colored(['green'], 'â') : ' ';
say " $marker " . ($i + 1) . ". $options->[$i]";
}
lib/App/GHGen/Interactive.pm view on Meta::CPAN
my @selected;
for my $num (split /[,\s]+/, $answer) {
if ($num =~ /^\d+$/ && $num >= 1 && $num <= @$options) {
push @selected, $options->[$num - 1];
}
}
return @selected ? \@selected : $defaults;
}
=head2 prompt_text($question, $default)
Prompt for text input.
=cut
sub prompt_text($question, $default = '') {
my $prompt = $default ? "[$default]" : '';
print "$question $prompt: ";
chomp(my $answer = <STDIN>);
return $answer eq '' ? $default : $answer;
}
=head2 customize_workflow($type)
Interactive customization for a specific workflow type.
Returns hash of configuration options.
lib/App/GHGen/Interactive.pm view on Meta::CPAN
}
sub _customize_perl() {
my %config;
# Perl versions
say colored(['bold'], "Perl Versions to Test:");
my @all_versions = qw(5.40 5.38 5.36 5.34 5.32 5.30 5.28 5.26 5.24 5.22);
my @default_versions = qw(5.40 5.38 5.36);
$config{perl_versions} = prompt_multiselect(
"Which Perl versions?",
\@all_versions,
\@default_versions
);
say '';
# Operating systems
say colored(['bold'], "Operating Systems:");
my @all_os = ('ubuntu-latest', 'macos-latest', 'windows-latest');
my @default_os = @all_os;
$config{os} = prompt_multiselect(
"Which operating systems?",
\@all_os,
\@default_os
);
say '';
# Code quality
say colored(['bold'], "Code Quality Tools:");
$config{enable_critic} = prompt_yes_no(
"Enable Perl::Critic?",
'y'
);
say '';
# Coverage
$config{enable_coverage} = prompt_yes_no(
"Enable test coverage (Devel::Cover)?",
'y'
);
say '';
# Branches
say colored(['bold'], "Branch Configuration:");
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main,master'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_node() {
my %config;
# Node versions
say colored(['bold'], "Node.js Versions to Test:");
my @all_versions = qw(18.x 20.x 22.x 23.x);
my @default_versions = qw(20.x 22.x);
$config{node_versions} = prompt_multiselect(
"Which Node.js versions?",
\@all_versions,
\@default_versions
);
say '';
# Package manager
say colored(['bold'], "Package Manager:");
my $pm_choice = prompt_choice(
"Which package manager?",
['npm', 'yarn', 'pnpm'],
0
);
$config{package_manager} = ['npm', 'yarn', 'pnpm']->[$pm_choice];
say '';
# Linting
$config{enable_lint} = prompt_yes_no(
"Enable linting?",
'y'
);
say '';
# Build step
$config{enable_build} = prompt_yes_no(
"Enable build step?",
'y'
);
say '';
# Branches
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main,develop'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_python() {
my %config;
# Python versions
say colored(['bold'], "Python Versions to Test:");
my @all_versions = qw(3.9 3.10 3.11 3.12 3.13);
my @default_versions = qw(3.11 3.12);
$config{python_versions} = prompt_multiselect(
"Which Python versions?",
\@all_versions,
\@default_versions
);
say '';
# Linting
say colored(['bold'], "Code Quality:");
$config{enable_flake8} = prompt_yes_no(
"Enable flake8 linting?",
'y'
);
say '';
$config{enable_black} = prompt_yes_no(
"Enable black formatter check?",
'n'
);
say '';
# Coverage
$config{enable_coverage} = prompt_yes_no(
"Enable test coverage?",
'y'
);
say '';
# Branches
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main,develop'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_rust() {
my %config;
say colored(['bold'], "Rust Workflow Options:");
$config{enable_fmt} = prompt_yes_no(
"Enable formatting check (cargo fmt)?",
'y'
);
say '';
$config{enable_clippy} = prompt_yes_no(
"Enable clippy linting?",
'y'
);
say '';
$config{enable_release} = prompt_yes_no(
"Build release binary?",
'y'
);
say '';
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_go() {
my %config;
say colored(['bold'], "Go Workflow Options:");
my $go_version = prompt_text(
"Go version",
'1.22'
);
$config{go_version} = $go_version;
say '';
$config{enable_vet} = prompt_yes_no(
"Enable go vet?",
'y'
);
say '';
$config{enable_race} = prompt_yes_no(
"Enable race detector?",
'y'
);
say '';
$config{enable_coverage} = prompt_yes_no(
"Enable test coverage?",
'y'
);
say '';
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_ruby() {
my %config;
say colored(['bold'], "Ruby Versions to Test:");
my @all_versions = qw(3.1 3.2 3.3);
my @default_versions = qw(3.2 3.3);
$config{ruby_versions} = prompt_multiselect(
"Which Ruby versions?",
\@all_versions,
\@default_versions
);
say '';
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_docker() {
my %config;
say colored(['bold'], "Docker Workflow Options:");
my $image_name = prompt_text(
"Docker image name (user/image)",
'your-username/your-image'
);
$config{image_name} = $image_name;
say '';
$config{push_on_pr} = prompt_yes_no(
'Push images on pull requests?',
'n'
);
say '';
my $branches = prompt_text(
"Branches to run on (comma-separated)",
'main'
);
$config{branches} = [split /,\s*/, $branches];
say '';
return \%config;
}
sub _customize_static() {
my %config;
say colored(['bold'], "Static Site Deployment:");
my $build_dir = prompt_text("Build output directory", './public');
$config{build_dir} = $build_dir;
say '';
my $build_command = prompt_text("Build command", 'npm run build');
$config{build_command} = $build_command;
say '';
return \%config;
}
=head1 AUTHOR
Nigel Horne E<lt>njh@nigelhorne.comE<gt>
( run in 1.067 second using v1.01-cache-2.11-cpan-6aa56a78535 )