App-GHGen
view release on metacpan or search on metacpan
lib/App/GHGen/Fixer.pm view on Meta::CPAN
}
# Rust
if ($run =~ /cargo (build|test)/) {
return {
name => 'Cache cargo',
uses => 'actions/cache@v5',
with => {
path => "~/.cargo/bin/\n~/.cargo/registry/index/\n~/.cargo/registry/cache/\n~/.cargo/git/db/\ntarget/",
key => '${{ runner.os }}-cargo-${{ hashFiles(\'**/Cargo.lock\') }}',
},
};
}
# Go
if ($run =~ /go (build|test)/ || ($step->{uses} && $step->{uses} =~ /setup-go/)) {
return {
name => 'Cache Go modules',
uses => 'actions/cache@v5',
with => {
path => '~/go/pkg/mod',
key => '${{ runner.os }}-go-${{ hashFiles(\'**/go.sum\') }}',
'restore-keys' => '${{ runner.os }}-go-',
},
};
}
}
return undef;
}
sub fix_unpinned_actions($workflow) {
my $jobs = $workflow->{jobs} or return 0;
my $modified = 0;
for my $job (values %$jobs) {
my $steps = $job->{steps} or next;
for my $step (@$steps) {
next unless $step->{uses};
if ($step->{uses} =~ /^(.+)\@(master|main)$/) {
my $action = $1;
# Map to appropriate version
my $version = get_latest_version($action);
$step->{uses} = "$action\@$version";
$modified++;
}
}
}
return $modified;
}
sub add_permissions($workflow) {
return 0 if $workflow->{permissions};
$workflow->{permissions} = { contents => 'read' };
return 1;
}
sub update_actions($workflow) {
my $jobs = $workflow->{jobs} or return 0;
my $modified = 0;
my %updates = (
'actions/cache@v4' => 'actions/cache@v5',
'actions/cache@v3' => 'actions/cache@v5',
'actions/checkout@v5' => 'actions/checkout@v6',
'actions/checkout@v4' => 'actions/checkout@v6',
'actions/checkout@v3' => 'actions/checkout@v6',
'actions/setup-node@v3' => 'actions/setup-node@v4',
'actions/setup-python@v4' => 'actions/setup-python@v5',
'actions/setup-go@v4' => 'actions/setup-go@v5',
);
for my $job (values %$jobs) {
my $steps = $job->{steps} or next;
for my $step (@$steps) {
next unless $step->{uses};
for my $old (keys %updates) {
if ($step->{uses} =~ /^\Q$old\E/) {
$step->{uses} = $updates{$old};
$modified++;
}
}
}
}
return $modified;
}
sub add_concurrency($workflow) {
return 0 if $workflow->{concurrency};
$workflow->{concurrency} = {
group => '${{ github.workflow }}-${{ github.ref }}',
'cancel-in-progress' => 'true',
};
return 1;
}
sub add_trigger_filters($workflow) {
my $on = $workflow->{on} or return 0;
my $modified = 0;
# If 'on' is just 'push', expand it
if (ref $on eq 'ARRAY' && grep { $_ eq 'push' } @$on) {
$workflow->{on} = {
push => {
branches => ['main', 'master'],
},
pull_request => {
branches => ['main', 'master'],
},
};
$modified++;
}
elsif (ref $on eq 'HASH' && $on->{push} && ref $on->{push} eq '') {
# 'push' with no filters
$on->{push} = {
branches => ['main', 'master'],
};
$modified++;
}
return $modified;
}
sub add_missing_timeout($workflow) {
my $jobs = $workflow->{jobs} or return 0;
my $modified = 0;
for my $job_name (keys %$jobs) {
my $job = $jobs->{$job_name};
# Skip if timeout already exists
next if exists $job->{'timeout-minutes'};
# Insert default timeout
$job->{'timeout-minutes'} = 30;
$modified++;
}
return $modified;
}
sub update_runners($workflow) {
my $jobs = $workflow->{jobs} or return 0;
my $modified = 0;
my %runner_updates = (
'ubuntu-18.04' => 'ubuntu-latest',
'ubuntu-16.04' => 'ubuntu-latest',
'macos-10.15' => 'macos-latest',
'windows-2016' => 'windows-latest',
);
for my $job (values %$jobs) {
my $runs_on = $job->{'runs-on'} or next;
if (exists $runner_updates{$runs_on}) {
$job->{'runs-on'} = $runner_updates{$runs_on};
$modified++;
}
}
return $modified;
}
sub get_latest_version($action) {
my %versions = (
'actions/checkout' => 'v6',
'actions/cache' => 'v5',
'actions/setup-node' => 'v4',
'actions/setup-python' => 'v5',
'actions/setup-go' => 'v5',
'actions/upload-artifact' => 'v4',
'actions/download-artifact' => 'v4',
);
return $versions{$action} // 'v4'; # Default fallback
}
=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 license terms.
The license terms of this software are as follows:
=cut
1;
( run in 0.502 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )