| File: | blib/lib/App/GHGen/Interactive.pm |
| Coverage: | 98.2% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package App::GHGen::Interactive; | |||||
| 2 | ||||||
| 3 | 4 4 | 541 5 | use v5.36; | |||
| 4 | 4 4 4 | 5 3 25 | use strict; | |||
| 5 | 4 4 4 | 4 3 61 | use warnings; | |||
| 6 | 4 4 4 | 794 12965 2199 | use Term::ANSIColor qw(colored); | |||
| 7 | ||||||
| 8 | 4 4 4 | 13 6 3044 | use Exporter 'import'; | |||
| 9 | our @EXPORT_OK = qw( | |||||
| 10 | prompt_yes_no | |||||
| 11 | prompt_choice | |||||
| 12 | prompt_multiselect | |||||
| 13 | prompt_text | |||||
| 14 | customize_workflow | |||||
| 15 | ); | |||||
| 16 | ||||||
| 17 | our $VERSION = '0.10'; | |||||
| 18 | ||||||
| 19 - 98 | =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
=encoding utf-8
=head1 FUNCTIONS
=head2 prompt_yes_no($question, $default)
Prompt the user for a yes/no answer and return a boolean.
=head3 Purpose
Print C<$question> followed by a bracket hint (C<[Y/n]> or C<[y/N]>),
read one line from STDIN, and return C<1> for yes or C<0> for no. An
empty response uses C<$default>.
=head3 Arguments
=over 4
=item C<$question> (Str, required)
The question text to display.
=item C<$default> (Str, optional, default C<'y'>)
The default answer when the user presses Enter without typing.
Must be C<'y'> or C<'n'>.
=back
=head3 Returns
C<1> when the answer is affirmative (C<y> or C<yes>, case-insensitive) or
when the empty response maps to a C<'y'> default.
C<0> when the answer is negative (C<n> or C<no>, case-insensitive) or
when the empty response maps to an C<'n'> default.
=head3 Side Effects
Reads one line from STDIN; prints to STDOUT.
=head3 Usage Example
my $ok = prompt_yes_no("Enable coverage?", 'y');
=head3 API SPECIFICATION
=head4 Input
{
question => { type => 'scalar', required => 1 },
default => { type => 'scalar', default => 'y' },
}
=head4 Output
{ type => 'scalar' } # 1 or 0
=head3 FORMAL SPECIFICATION
prompt_yes_no : â¤* à {'y','n'} â ð¹
answer â chomp(readline(STDIN))
result â
answer =~ /^y(?:es)?$/i â 1
answer =~ /^n(?:o)?$/i â 0
answer = "" â default = 'y' â 1 | default = 'n' â 0
=cut | |||||
| 99 | ||||||
| 100 | 27 27 27 27 | 3288 14 19 9 | sub prompt_yes_no($question, $default = 'y') { | |||
| 101 | 27 | 24 | my $prompt = $default eq 'y' ? '[Y/n]' : '[y/N]'; | |||
| 102 | 27 | 31 | print "$question $prompt: "; | |||
| 103 | 27 | 26 | chomp(my $answer = <STDIN>); | |||
| 104 | ||||||
| 105 | 27 | 53 | return 1 if $answer =~ /^y(?:es)?$/i; | |||
| 106 | 10 | 24 | return 0 if $answer =~ /^n(?:o)?$/i; | |||
| 107 | 4 | 12 | return $default eq 'y' ? 1 : 0; | |||
| 108 | } | |||||
| 109 | ||||||
| 110 - 175 | =head2 prompt_choice($question, $choices, $default)
Prompt the user to select one item from a numbered list.
=head3 Purpose
Display C<$question> followed by a numbered list of C<$choices>, read one
line from STDIN, and return the zero-based index of the selected item.
=head3 Arguments
=over 4
=item C<$question> (Str, required)
The selection prompt text.
=item C<$choices> (ArrayRef[Str], required)
The available options, displayed numbered from 1.
=item C<$default> (Int, optional, default C<0>)
Zero-based index of the pre-selected option shown in the prompt.
=back
=head3 Returns
A zero-based integer index. Returns C<$default> when the user presses Enter
without input or when the input is out of range (less than 1 or greater than
the number of choices).
=head3 Side Effects
Reads one line from STDIN; prints to STDOUT.
=head3 Usage Example
my $idx = prompt_choice("Package manager?", ['npm','yarn','pnpm'], 0);
=head3 API SPECIFICATION
=head4 Input
{
question => { type => 'scalar', required => 1 },
choices => { type => 'arrayref', required => 1 },
default => { type => 'scalar', default => 0 },
}
=head4 Output
{ type => 'scalar' } # integer 0 .. |choices|-1
=head3 FORMAL SPECIFICATION
prompt_choice : â¤* à seq â¤* à â â â
answer â chomp(readline(STDIN))
result â
answer = "" â default
answer â â â§ 1 ⤠answer ⤠|choices| â answer â 1
otherwise â default
=cut | |||||
| 176 | ||||||
| 177 | 12 12 12 12 12 | 10331 8 9 9 6 | sub prompt_choice($question, $choices, $default = 0) { | |||
| 178 | 12 | 44 | say $question; | |||
| 179 | 12 | 21 | for my $i (0 .. $#$choices) { | |||
| 180 | 36 | 81 | my $marker = $i == $default ? colored(['green'], 'â') : ' '; | |||
| 181 | 36 | 270 | say " $marker " . ($i + 1) . ". $choices->[$i]"; | |||
| 182 | } | |||||
| 183 | ||||||
| 184 | 12 | 25 | print "\nEnter number [" . ($default + 1) . "]: "; | |||
| 185 | 12 | 14 | chomp(my $answer = <STDIN>); | |||
| 186 | ||||||
| 187 | 12 | 21 | return $default if $answer eq ''; | |||
| 188 | 9 | 39 | return $answer - 1 if $answer =~ /^\d+$/ && $answer >= 1 && $answer <= @$choices; | |||
| 189 | 4 | 14 | return $default; | |||
| 190 | } | |||||
| 191 | ||||||
| 192 - 273 | =head2 prompt_multiselect($question, $options, $defaults)
Prompt the user to select zero or more items from a numbered list.
=head3 Purpose
Display C<$question> and a numbered list of C<$options>, accept
comma-separated numbers or the keyword C<all>, and return an array reference
of the selected option strings.
=head3 Arguments
=over 4
=item C<$question> (Str, required)
The multi-select prompt text.
=item C<$options> (ArrayRef[Str], required)
All available options, displayed numbered from 1.
=item C<$defaults> (ArrayRef[Str], optional, default C<[]>)
The pre-selected options (by value, not index).
=back
=head3 Returns
An array reference of selected option strings. Possible values:
=over 4
=item *
The full C<$options> list when the user types C<all>.
=item *
A subset derived from the comma/space-separated numbers the user entered.
=item *
C<$defaults> when the user presses Enter without typing.
=back
=head3 Side Effects
Reads one line from STDIN; prints to STDOUT.
=head3 Usage Example
my $sel = prompt_multiselect("OS?", ['ubuntu-latest','macos-latest','windows-latest'], []);
=head3 API SPECIFICATION
=head4 Input
{
question => { type => 'scalar', required => 1 },
options => { type => 'arrayref', required => 1 },
defaults => { type => 'arrayref', default => [] },
}
=head4 Output
{ type => 'arrayref' }
=head3 FORMAL SPECIFICATION
prompt_multiselect : â¤* à seq â¤* à seq â¤* â seq â¤*
answer â chomp(readline(STDIN))
result â
answer = "" â defaults
answer =~ /^all$/i â options
otherwise â [ options[nâ1] ⣠n â split(/[,\s]+/, answer), 1 ⤠n ⤠|options| ]
?? defaults (when result = â
)
=cut | |||||
| 274 | ||||||
| 275 | 13 13 13 13 13 | 5447 9 7 8 8 | sub prompt_multiselect($question, $options, $defaults = []) { | |||
| 276 | 13 | 21 | say $question; | |||
| 277 | 13 | 18 | say colored(['cyan'], "(Enter numbers separated by commas, or 'all')"); | |||
| 278 | ||||||
| 279 | 13 25 | 187 26 | my %is_default = map { $_ => 1 } @$defaults; | |||
| 280 | ||||||
| 281 | 13 | 18 | for my $i (0 .. $#$options) { | |||
| 282 | 55 | 89 | my $marker = $is_default{$options->[$i]} ? colored(['green'], 'â') : ' '; | |||
| 283 | 55 | 341 | say " $marker " . ($i + 1) . ". $options->[$i]"; | |||
| 284 | } | |||||
| 285 | ||||||
| 286 | 13 25 | 18 37 | print "\nEnter choices [" . join(',', map { $_+1 } 0..$#$defaults) . "]: "; | |||
| 287 | 13 | 23 | chomp(my $answer = <STDIN>); | |||
| 288 | ||||||
| 289 | 13 | 15 | return $defaults if $answer eq ''; | |||
| 290 | ||||||
| 291 | 11 | 16 | if ($answer =~ /^all$/i) { | |||
| 292 | 2 | 5 | return $options; | |||
| 293 | } | |||||
| 294 | ||||||
| 295 | 9 | 5 | my @selected; | |||
| 296 | 9 | 19 | for my $num (split /[,\s]+/, $answer) { | |||
| 297 | 19 | 54 | if ($num =~ /^\d+$/ && $num >= 1 && $num <= @$options) { | |||
| 298 | 17 | 17 | push @selected, $options->[$num - 1]; | |||
| 299 | } | |||||
| 300 | } | |||||
| 301 | ||||||
| 302 | 9 | 23 | return @selected ? \@selected : $defaults; | |||
| 303 | } | |||||
| 304 | ||||||
| 305 - 360 | =head2 prompt_text($question, $default)
Prompt the user for a free-form text answer.
=head3 Purpose
Display C<$question> optionally followed by C<[$default]>, read one line
from STDIN, and return the user's answer or C<$default> when empty.
=head3 Arguments
=over 4
=item C<$question> (Str, required)
The prompt text.
=item C<$default> (Str, optional, default C<''>)
Returned as-is when the user presses Enter without typing anything.
=back
=head3 Returns
The trimmed line the user typed, or C<$default> when the input is empty.
=head3 Side Effects
Reads one line from STDIN; prints to STDOUT.
=head3 Usage Example
my $name = prompt_text("Project name", 'my-project');
=head3 API SPECIFICATION
=head4 Input
{
question => { type => 'scalar', required => 1 },
default => { type => 'scalar', default => '' },
}
=head4 Output
{ type => 'scalar' }
=head3 FORMAL SPECIFICATION
prompt_text : â¤* à â¤* â â¤*
answer â chomp(readline(STDIN))
result â answer = "" â default | otherwise â answer
=cut | |||||
| 361 | ||||||
| 362 | 15 15 15 15 | 2751 6 12 4 | sub prompt_text($question, $default = '') { | |||
| 363 | 15 | 20 | my $prompt = $default ? "[$default]" : ''; | |||
| 364 | 15 | 18 | print "$question $prompt: "; | |||
| 365 | 15 | 15 | chomp(my $answer = <STDIN>); | |||
| 366 | ||||||
| 367 | 15 | 24 | return $answer eq '' ? $default : $answer; | |||
| 368 | } | |||||
| 369 | ||||||
| 370 - 424 | =head2 customize_workflow($type)
Drive an interactive customization session for the given workflow type.
=head3 Purpose
Display a series of prompts relevant to C<$type> and collect user preferences.
Dispatches to a private C<_customize_*> helper; returns an empty hash when
the type is not supported.
=head3 Arguments
=over 4
=item C<$type> (Str, required)
The workflow type to customise. Supported: C<perl>, C<node>, C<python>,
C<rust>, C<go>, C<ruby>, C<docker>, C<static>.
=back
=head3 Returns
A hash reference of configuration key/value pairs collected from the user.
Returns an empty hash reference (C<{}>) when C<$type> is not recognised.
=head3 Side Effects
Reads multiple lines from STDIN; prints to STDOUT.
=head3 Usage Example
my $config = customize_workflow('perl');
# $config->{enable_critic}, $config->{perl_versions}, etc.
=head3 API SPECIFICATION
=head4 Input
{ type => { type => 'scalar', required => 1 } }
=head4 Output
{ type => 'hashref' } # empty or populated with type-specific keys
=head3 FORMAL SPECIFICATION
SupportedCustomTypes â { perl, node, python, rust, go, ruby, docker, static }
customize_workflow : â¤* â Config
t â SupportedCustomTypes â _customize_t()
t â SupportedCustomTypes â {}
=cut | |||||
| 425 | ||||||
| 426 | 10 10 10 | 14791 10 7 | sub customize_workflow($type) { | |||
| 427 | 10 | 45 | say ''; | |||
| 428 | 10 | 29 | say colored(['bold cyan'], "=== Workflow Customization: " . uc($type) . " ==="); | |||
| 429 | 10 | 230 | say ''; | |||
| 430 | ||||||
| 431 | 10 | 34 | my %dispatch = ( | |||
| 432 | perl => \&_customize_perl, | |||||
| 433 | node => \&_customize_node, | |||||
| 434 | python => \&_customize_python, | |||||
| 435 | rust => \&_customize_rust, | |||||
| 436 | go => \&_customize_go, | |||||
| 437 | ruby => \&_customize_ruby, | |||||
| 438 | docker => \&_customize_docker, | |||||
| 439 | static => \&_customize_static, | |||||
| 440 | ); | |||||
| 441 | ||||||
| 442 | 10 | 17 | if (exists $dispatch{$type}) { | |||
| 443 | 8 | 9 | return $dispatch{$type}->(); | |||
| 444 | } | |||||
| 445 | ||||||
| 446 | 2 | 6 | return {}; | |||
| 447 | } | |||||
| 448 | ||||||
| 449 | 1 1 | 1 0 | sub _customize_perl() { | |||
| 450 | 1 | 1 | my %config; | |||
| 451 | ||||||
| 452 | # Perl versions | |||||
| 453 | 1 | 2 | say colored(['bold'], "Perl Versions to Test:"); | |||
| 454 | 1 | 16 | my @all_versions = qw(5.40 5.38 5.36 5.34 5.32 5.30 5.28 5.26 5.24 5.22); | |||
| 455 | 1 | 2 | my @default_versions = qw(5.40 5.38 5.36); | |||
| 456 | ||||||
| 457 | 1 | 2 | $config{perl_versions} = prompt_multiselect( | |||
| 458 | "Which Perl versions?", | |||||
| 459 | \@all_versions, | |||||
| 460 | \@default_versions | |||||
| 461 | ); | |||||
| 462 | 1 | 1 | say ''; | |||
| 463 | ||||||
| 464 | # Operating systems | |||||
| 465 | 1 | 2 | say colored(['bold'], "Operating Systems:"); | |||
| 466 | 1 | 14 | my @all_os = ('ubuntu-latest', 'macos-latest', 'windows-latest'); | |||
| 467 | 1 | 1 | my @default_os = @all_os; | |||
| 468 | ||||||
| 469 | 1 | 2 | $config{os} = prompt_multiselect( | |||
| 470 | "Which operating systems?", | |||||
| 471 | \@all_os, | |||||
| 472 | \@default_os | |||||
| 473 | ); | |||||
| 474 | 1 | 1 | say ''; | |||
| 475 | ||||||
| 476 | # Code quality | |||||
| 477 | 1 | 2 | say colored(['bold'], "Code Quality Tools:"); | |||
| 478 | 1 | 13 | $config{enable_linter} = prompt_yes_no( | |||
| 479 | "Enable syntax linting (perl -c on all matrix cells)?", | |||||
| 480 | 'y' | |||||
| 481 | ); | |||||
| 482 | 1 | 1 | say ''; | |||
| 483 | ||||||
| 484 | 1 | 1 | $config{enable_linter_unused} = prompt_yes_no( | |||
| 485 | "Enable unused-variable check (warnings::unused, latest+ubuntu only)?", | |||||
| 486 | 'n' | |||||
| 487 | ); | |||||
| 488 | 1 | 2 | say ''; | |||
| 489 | ||||||
| 490 | 1 | 1 | $config{enable_critic} = prompt_yes_no( | |||
| 491 | "Enable Perl::Critic?", | |||||
| 492 | 'y' | |||||
| 493 | ); | |||||
| 494 | 1 | 1 | say ''; | |||
| 495 | ||||||
| 496 | # Coverage | |||||
| 497 | 1 | 1 | $config{enable_coverage} = prompt_yes_no( | |||
| 498 | "Enable test coverage (Devel::Cover)?", | |||||
| 499 | 'y' | |||||
| 500 | ); | |||||
| 501 | 1 | 1 | say ''; | |||
| 502 | ||||||
| 503 | # Branches | |||||
| 504 | 1 | 2 | say colored(['bold'], "Branch Configuration:"); | |||
| 505 | 1 | 13 | my $branches = prompt_text( | |||
| 506 | "Branches to run on (comma-separated)", | |||||
| 507 | 'main,master' | |||||
| 508 | ); | |||||
| 509 | 1 | 2 | $config{branches} = [split /,\s*/, $branches]; | |||
| 510 | 1 | 2 | say ''; | |||
| 511 | ||||||
| 512 | 1 | 4 | return \%config; | |||
| 513 | } | |||||
| 514 | ||||||
| 515 | 1 1 | 1 1 | sub _customize_node() { | |||
| 516 | 1 | 1 | my %config; | |||
| 517 | ||||||
| 518 | # Node versions | |||||
| 519 | 1 | 1 | say colored(['bold'], "Node.js Versions to Test:"); | |||
| 520 | 1 | 16 | my @all_versions = qw(18.x 20.x 22.x 23.x); | |||
| 521 | 1 | 1 | my @default_versions = qw(20.x 22.x); | |||
| 522 | ||||||
| 523 | 1 | 2 | $config{node_versions} = prompt_multiselect( | |||
| 524 | "Which Node.js versions?", | |||||
| 525 | \@all_versions, | |||||
| 526 | \@default_versions | |||||
| 527 | ); | |||||
| 528 | 1 | 1 | say ''; | |||
| 529 | ||||||
| 530 | # Package manager | |||||
| 531 | 1 | 2 | say colored(['bold'], "Package Manager:"); | |||
| 532 | 1 | 14 | my $pm_choice = prompt_choice( | |||
| 533 | "Which package manager?", | |||||
| 534 | ['npm', 'yarn', 'pnpm'], | |||||
| 535 | 0 | |||||
| 536 | ); | |||||
| 537 | 1 | 2 | $config{package_manager} = ['npm', 'yarn', 'pnpm']->[$pm_choice]; | |||
| 538 | 1 | 2 | say ''; | |||
| 539 | ||||||
| 540 | # Linting | |||||
| 541 | 1 | 1 | $config{enable_lint} = prompt_yes_no( | |||
| 542 | "Enable linting?", | |||||
| 543 | 'y' | |||||
| 544 | ); | |||||
| 545 | 1 | 1 | say ''; | |||
| 546 | ||||||
| 547 | # Build step | |||||
| 548 | 1 | 1 | $config{enable_build} = prompt_yes_no( | |||
| 549 | "Enable build step?", | |||||
| 550 | 'y' | |||||
| 551 | ); | |||||
| 552 | 1 | 1 | say ''; | |||
| 553 | ||||||
| 554 | # Branches | |||||
| 555 | 1 | 1 | my $branches = prompt_text( | |||
| 556 | "Branches to run on (comma-separated)", | |||||
| 557 | 'main,develop' | |||||
| 558 | ); | |||||
| 559 | 1 | 2 | $config{branches} = [split /,\s*/, $branches]; | |||
| 560 | 1 | 1 | say ''; | |||
| 561 | ||||||
| 562 | 1 | 4 | return \%config; | |||
| 563 | } | |||||
| 564 | ||||||
| 565 | 1 1 | 1 1 | sub _customize_python() { | |||
| 566 | 1 | 1 | my %config; | |||
| 567 | ||||||
| 568 | # Python versions | |||||
| 569 | 1 | 1 | say colored(['bold'], "Python Versions to Test:"); | |||
| 570 | 1 | 15 | my @all_versions = qw(3.9 3.10 3.11 3.12 3.13); | |||
| 571 | 1 | 2 | my @default_versions = qw(3.11 3.12); | |||
| 572 | ||||||
| 573 | 1 | 1 | $config{python_versions} = prompt_multiselect( | |||
| 574 | "Which Python versions?", | |||||
| 575 | \@all_versions, | |||||
| 576 | \@default_versions | |||||
| 577 | ); | |||||
| 578 | 1 | 2 | say ''; | |||
| 579 | ||||||
| 580 | # Linting | |||||
| 581 | 1 | 1 | say colored(['bold'], "Code Quality:"); | |||
| 582 | 1 | 14 | $config{enable_flake8} = prompt_yes_no( | |||
| 583 | "Enable flake8 linting?", | |||||
| 584 | 'y' | |||||
| 585 | ); | |||||
| 586 | 1 | 1 | say ''; | |||
| 587 | ||||||
| 588 | 1 | 1 | $config{enable_black} = prompt_yes_no( | |||
| 589 | "Enable black formatter check?", | |||||
| 590 | 'n' | |||||
| 591 | ); | |||||
| 592 | 1 | 1 | say ''; | |||
| 593 | ||||||
| 594 | # Coverage | |||||
| 595 | 1 | 1 | $config{enable_coverage} = prompt_yes_no( | |||
| 596 | "Enable test coverage?", | |||||
| 597 | 'y' | |||||
| 598 | ); | |||||
| 599 | 1 | 1 | say ''; | |||
| 600 | ||||||
| 601 | # Branches | |||||
| 602 | 1 | 2 | my $branches = prompt_text( | |||
| 603 | "Branches to run on (comma-separated)", | |||||
| 604 | 'main,develop' | |||||
| 605 | ); | |||||
| 606 | 1 | 2 | $config{branches} = [split /,\s*/, $branches]; | |||
| 607 | 1 | 1 | say ''; | |||
| 608 | ||||||
| 609 | 1 | 4 | return \%config; | |||
| 610 | } | |||||
| 611 | ||||||
| 612 | 1 1 | 1 1 | sub _customize_rust() { | |||
| 613 | 1 | 1 | my %config; | |||
| 614 | ||||||
| 615 | 1 | 2 | say colored(['bold'], "Rust Workflow Options:"); | |||
| 616 | ||||||
| 617 | 1 | 15 | $config{enable_fmt} = prompt_yes_no( | |||
| 618 | "Enable formatting check (cargo fmt)?", | |||||
| 619 | 'y' | |||||
| 620 | ); | |||||
| 621 | 1 | 2 | say ''; | |||
| 622 | ||||||
| 623 | 1 | 1 | $config{enable_clippy} = prompt_yes_no( | |||
| 624 | "Enable clippy linting?", | |||||
| 625 | 'y' | |||||
| 626 | ); | |||||
| 627 | 1 | 2 | say ''; | |||
| 628 | ||||||
| 629 | 1 | 1 | $config{enable_release} = prompt_yes_no( | |||
| 630 | "Build release binary?", | |||||
| 631 | 'y' | |||||
| 632 | ); | |||||
| 633 | 1 | 1 | say ''; | |||
| 634 | ||||||
| 635 | 1 | 2 | my $branches = prompt_text( | |||
| 636 | "Branches to run on (comma-separated)", | |||||
| 637 | 'main' | |||||
| 638 | ); | |||||
| 639 | 1 | 3 | $config{branches} = [split /,\s*/, $branches]; | |||
| 640 | 1 | 2 | say ''; | |||
| 641 | ||||||
| 642 | 1 | 3 | return \%config; | |||
| 643 | } | |||||
| 644 | ||||||
| 645 | 1 1 | 1 1 | sub _customize_go() { | |||
| 646 | 1 | 1 | my %config; | |||
| 647 | ||||||
| 648 | 1 | 11 | say colored(['bold'], "Go Workflow Options:"); | |||
| 649 | ||||||
| 650 | 1 | 15 | my $go_version = prompt_text( | |||
| 651 | "Go version", | |||||
| 652 | '1.22' | |||||
| 653 | ); | |||||
| 654 | 1 | 1 | $config{go_version} = $go_version; | |||
| 655 | 1 | 2 | say ''; | |||
| 656 | ||||||
| 657 | 1 | 1 | $config{enable_vet} = prompt_yes_no( | |||
| 658 | "Enable go vet?", | |||||
| 659 | 'y' | |||||
| 660 | ); | |||||
| 661 | 1 | 1 | say ''; | |||
| 662 | ||||||
| 663 | 1 | 2 | $config{enable_race} = prompt_yes_no( | |||
| 664 | "Enable race detector?", | |||||
| 665 | 'y' | |||||
| 666 | ); | |||||
| 667 | 1 | 1 | say ''; | |||
| 668 | ||||||
| 669 | 1 | 2 | $config{enable_coverage} = prompt_yes_no( | |||
| 670 | "Enable test coverage?", | |||||
| 671 | 'y' | |||||
| 672 | ); | |||||
| 673 | 1 | 2 | say ''; | |||
| 674 | ||||||
| 675 | 1 | 2 | my $branches = prompt_text( | |||
| 676 | "Branches to run on (comma-separated)", | |||||
| 677 | 'main' | |||||
| 678 | ); | |||||
| 679 | 1 | 2 | $config{branches} = [split /,\s*/, $branches]; | |||
| 680 | 1 | 1 | say ''; | |||
| 681 | ||||||
| 682 | 1 | 4 | return \%config; | |||
| 683 | } | |||||
| 684 | ||||||
| 685 | 1 1 | 1 1 | sub _customize_ruby() { | |||
| 686 | 1 | 1 | my %config; | |||
| 687 | ||||||
| 688 | 1 | 2 | say colored(['bold'], "Ruby Versions to Test:"); | |||
| 689 | 1 | 15 | my @all_versions = qw(3.1 3.2 3.3); | |||
| 690 | 1 | 1 | my @default_versions = qw(3.2 3.3); | |||
| 691 | ||||||
| 692 | 1 | 2 | $config{ruby_versions} = prompt_multiselect( | |||
| 693 | "Which Ruby versions?", | |||||
| 694 | \@all_versions, | |||||
| 695 | \@default_versions | |||||
| 696 | ); | |||||
| 697 | 1 | 1 | say ''; | |||
| 698 | ||||||
| 699 | 1 | 1 | my $branches = prompt_text( | |||
| 700 | "Branches to run on (comma-separated)", | |||||
| 701 | 'main' | |||||
| 702 | ); | |||||
| 703 | 1 | 1 | $config{branches} = [split /,\s*/, $branches]; | |||
| 704 | 1 | 2 | say ''; | |||
| 705 | ||||||
| 706 | 1 | 3 | return \%config; | |||
| 707 | } | |||||
| 708 | ||||||
| 709 | 1 1 | 1 0 | sub _customize_docker() { | |||
| 710 | 1 | 1 | my %config; | |||
| 711 | ||||||
| 712 | 1 | 2 | say colored(['bold'], "Docker Workflow Options:"); | |||
| 713 | ||||||
| 714 | 1 | 14 | my $image_name = prompt_text( | |||
| 715 | "Docker image name (user/image)", | |||||
| 716 | 'your-username/your-image' | |||||
| 717 | ); | |||||
| 718 | 1 | 2 | $config{image_name} = $image_name; | |||
| 719 | 1 | 1 | say ''; | |||
| 720 | ||||||
| 721 | 1 | 2 | $config{push_on_pr} = prompt_yes_no( | |||
| 722 | 'Push images on pull requests?', | |||||
| 723 | 'n' | |||||
| 724 | ); | |||||
| 725 | 1 | 2 | say ''; | |||
| 726 | ||||||
| 727 | 1 | 1 | my $branches = prompt_text( | |||
| 728 | "Branches to run on (comma-separated)", | |||||
| 729 | 'main' | |||||
| 730 | ); | |||||
| 731 | 1 | 2 | $config{branches} = [split /,\s*/, $branches]; | |||
| 732 | 1 | 2 | say ''; | |||
| 733 | ||||||
| 734 | 1 | 3 | return \%config; | |||
| 735 | } | |||||
| 736 | ||||||
| 737 | 1 1 | 1 0 | sub _customize_static() { | |||
| 738 | 1 | 1 | my %config; | |||
| 739 | ||||||
| 740 | 1 | 2 | say colored(['bold'], "Static Site Deployment:"); | |||
| 741 | ||||||
| 742 | 1 | 14 | my $build_dir = prompt_text('Build output directory', './public'); | |||
| 743 | 1 | 2 | $config{build_dir} = $build_dir; | |||
| 744 | 1 | 1 | say ''; | |||
| 745 | ||||||
| 746 | 1 | 1 | my $build_command = prompt_text("Build command", 'npm run build'); | |||
| 747 | 1 | 2 | $config{build_command} = $build_command; | |||
| 748 | 1 | 1 | say ''; | |||
| 749 | ||||||
| 750 | 1 | 3 | return \%config; | |||
| 751 | } | |||||
| 752 | ||||||
| 753 - 767 | =head1 AUTHOR Nigel Horne E<lt>njh@nigelhorne.comE<gt> L<https://github.com/nigelhorne> =head1 COPYRIGHT AND LICENSE Copyright 2025-2026 Nigel Horne. Usage is subject to the GPL2 licence terms. If you use it, please let me know. =cut | |||||
| 768 | ||||||
| 769 | 1; | |||||