diff options
Diffstat (limited to 'lib/Devscripts/Salsa/check_repo.pm')
-rwxr-xr-x | lib/Devscripts/Salsa/check_repo.pm | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/lib/Devscripts/Salsa/check_repo.pm b/lib/Devscripts/Salsa/check_repo.pm new file mode 100755 index 0000000..c9de322 --- /dev/null +++ b/lib/Devscripts/Salsa/check_repo.pm @@ -0,0 +1,224 @@ +# 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; |