224 lines
8.1 KiB
Perl
Executable file
224 lines
8.1 KiB
Perl
Executable file
# Parses repo to check if parameters are well set
|
|
package Devscripts::Salsa::check_repo;
|
|
|
|
use strict;
|
|
use Devscripts::Output;
|
|
use Digest::MD5 qw(md5_hex);
|
|
use Digest::file qw(digest_file_hex);
|
|
use LWP::UserAgent;
|
|
use Moo::Role;
|
|
|
|
with "Devscripts::Salsa::Repo";
|
|
|
|
sub check_repo {
|
|
my $self = shift;
|
|
my ($res) = $self->_check_repo(@_);
|
|
return $res;
|
|
}
|
|
|
|
sub _url_md5_hex {
|
|
my $url = shift;
|
|
my $ua = LWP::UserAgent->new;
|
|
my $res = $ua->get($url, "User-Agent" => "Devscripts/2.22.3",);
|
|
if (!$res->is_success) {
|
|
return undef;
|
|
}
|
|
return Digest::MD5::md5_hex($res->content);
|
|
}
|
|
|
|
sub _check_repo {
|
|
my ($self, @reponames) = @_;
|
|
my $res = 0;
|
|
my @fail;
|
|
unless (@reponames or $self->config->all or $self->config->all_archived) {
|
|
ds_warn "Usage $0 check_repo <--all|--all-archived|names>";
|
|
return 1;
|
|
}
|
|
if (@reponames and $self->config->all) {
|
|
ds_warn "--all with a reponame makes no sense";
|
|
return 1;
|
|
}
|
|
if (@reponames and $self->config->all_archived) {
|
|
ds_warn "--all-archived with a reponame makes no sense";
|
|
return 1;
|
|
}
|
|
# Get repo list from Devscripts::Salsa::Repo
|
|
my @repos = $self->get_repo(0, @reponames);
|
|
return @repos unless (ref $repos[0]);
|
|
foreach my $repo (@repos) {
|
|
my @err;
|
|
my ($id, $name) = @$repo;
|
|
my $project = eval { $self->api->project($id) };
|
|
unless ($project) {
|
|
ds_debug $@;
|
|
ds_warn "Project $name not found";
|
|
next;
|
|
}
|
|
ds_debug "Checking $name ($id)";
|
|
# check description
|
|
my %prms = $self->desc($name);
|
|
my %prms_multipart = $self->desc_multipart($name);
|
|
if ($self->config->desc) {
|
|
$project->{description} //= '';
|
|
push @err, "bad description: $project->{description}"
|
|
if ($prms{description} ne $project->{description});
|
|
}
|
|
# check build timeout
|
|
if ($self->config->desc) {
|
|
$project->{build_timeout} //= '';
|
|
push @err, "bad build_timeout: $project->{build_timeout}"
|
|
if ($prms{build_timeout} ne $project->{build_timeout});
|
|
}
|
|
# check features (w/permission) & ci config
|
|
foreach (qw(
|
|
analytics_access_level
|
|
auto_devops_enabled
|
|
builds_access_level
|
|
ci_config_path
|
|
container_registry_access_level
|
|
environments_access_level
|
|
feature_flags_access_level
|
|
forking_access_level
|
|
infrastructure_access_level
|
|
issues_access_level
|
|
lfs_enabled
|
|
merge_requests_access_level
|
|
monitor_access_level
|
|
packages_enabled
|
|
pages_access_level
|
|
releases_access_level
|
|
remove_source_branch_after_merge
|
|
repository_access_level
|
|
request_access_enabled
|
|
requirements_access_level
|
|
security_and_compliance_access_level
|
|
service_desk_enabled
|
|
snippets_access_level
|
|
wiki_access_level
|
|
)
|
|
) {
|
|
my $helptext = '';
|
|
$helptext = ' (enabled)'
|
|
if (defined $prms{$_} and $prms{$_} eq 1);
|
|
$helptext = ' (disabled)'
|
|
if (defined $prms{$_} and $prms{$_} eq 0);
|
|
push @err, "$_ should be $prms{$_}$helptext"
|
|
if (defined $prms{$_}
|
|
and (!defined($project->{$_}) or $project->{$_} ne $prms{$_}));
|
|
}
|
|
# only public projects are accepted
|
|
push @err, "Project visibility: $project->{visibility}"
|
|
unless ($project->{visibility} eq "public");
|
|
# Default branch
|
|
if ($self->config->rename_head) {
|
|
push @err, "Default branch: $project->{default_branch}"
|
|
if ($project->{default_branch} ne $self->config->dest_branch);
|
|
}
|
|
# Webhooks (from Devscripts::Salsa::Hooks)
|
|
my $hooks = $self->enabled_hooks($id);
|
|
unless (defined $hooks) {
|
|
ds_warn "Unable to get $name hooks";
|
|
next;
|
|
}
|
|
# check avatar's path
|
|
if ($self->config->avatar_path) {
|
|
my ($md5_file, $md5_url) = "";
|
|
if ($prms_multipart{avatar}) {
|
|
ds_verbose "Calculating local avatar checksum";
|
|
$md5_file = digest_file_hex($prms_multipart{avatar}, "MD5")
|
|
or die "$prms_multipart{avatar} failed md5: $!";
|
|
if ( $project->{avatar_url}
|
|
and $project->{visibility} eq "public") {
|
|
ds_verbose "Calculating remote avatar checksum";
|
|
$md5_url = _url_md5_hex($project->{avatar_url})
|
|
or die "$project->{avatar_url} failed md5: $!";
|
|
# Will always force avatar if it can't detect
|
|
} elsif ($project->{avatar_url}) {
|
|
ds_warn
|
|
"$name has an avatar, but is set to $project->{visibility} project visibility thus unable to remotely check checksum";
|
|
}
|
|
push @err, "Will set the avatar to be: $prms_multipart{avatar}"
|
|
if (not length $md5_url or $md5_file ne $md5_url);
|
|
}
|
|
}
|
|
# KGB
|
|
if ($self->config->kgb and not $hooks->{kgb}) {
|
|
push @err, "kgb missing";
|
|
} elsif ($self->config->disable_kgb and $hooks->{kgb}) {
|
|
push @err, "kgb enabled";
|
|
} elsif ($self->config->kgb) {
|
|
push @err,
|
|
"bad irc channel: "
|
|
. substr($hooks->{kgb}->{url},
|
|
length($self->config->kgb_server_url))
|
|
if $hooks->{kgb}->{url} ne $self->config->kgb_server_url
|
|
. $self->config->irc_channel->[0];
|
|
my @wopts = @{ $self->config->kgb_options };
|
|
my @gopts = sort @{ $hooks->{kgb}->{options} };
|
|
my $i = 0;
|
|
while (@gopts and @wopts) {
|
|
my $a;
|
|
$a = ($wopts[0] cmp $gopts[0]);
|
|
if ($a == -1) {
|
|
push @err, "Missing KGB option " . shift(@wopts);
|
|
} elsif ($a == 1) {
|
|
push @err, 'Unwanted KGB option ' . shift(@gopts);
|
|
} else {
|
|
shift @wopts;
|
|
shift @gopts;
|
|
}
|
|
}
|
|
push @err, map { "Missing KGB option $_" } @wopts;
|
|
push @err, map { "Unwanted KGB option $_" } @gopts;
|
|
}
|
|
# Email-on-push
|
|
if ($self->config->email
|
|
and not($hooks->{email} and %{ $hooks->{email} })) {
|
|
push @err, "email-on-push missing";
|
|
} elsif (
|
|
$self->config->email
|
|
and $hooks->{email}->{recipients} ne join(
|
|
' ',
|
|
map {
|
|
my $a = $_;
|
|
my $b = $name;
|
|
$b =~ s#.*/##;
|
|
$a =~ s/%p/$b/;
|
|
$a
|
|
} @{ $self->config->email_recipient })
|
|
) {
|
|
push @err, "bad email recipients " . $hooks->{email}->{recipients};
|
|
} elsif ($self->config->disable_email and $hooks->{kgb}) {
|
|
push @err, "email-on-push enabled";
|
|
}
|
|
# Irker
|
|
if ($self->config->irker and not $hooks->{irker}) {
|
|
push @err, "irker missing";
|
|
} elsif ($self->config->irker
|
|
and $hooks->{irker}->{recipients} ne
|
|
join(' ', map { "#$_" } @{ $self->config->irc_channel })) {
|
|
push @err, "bad irc channel: " . $hooks->{irker}->{recipients};
|
|
} elsif ($self->config->disable_irker and $hooks->{irker}) {
|
|
push @err, "irker enabled";
|
|
}
|
|
# Tagpending
|
|
if ($self->config->tagpending and not $hooks->{tagpending}) {
|
|
push @err, "tagpending missing";
|
|
} elsif ($self->config->disable_tagpending
|
|
and $hooks->{tagpending}) {
|
|
push @err, "tagpending enabled";
|
|
}
|
|
# report errors
|
|
if (@err) {
|
|
$res++;
|
|
push @fail, $name;
|
|
print "$name:\n";
|
|
print "\t$_\n" foreach (@err);
|
|
} else {
|
|
ds_verbose "$name: OK";
|
|
}
|
|
}
|
|
return ($res, \@fail);
|
|
}
|
|
|
|
1;
|