314 lines
12 KiB
Perl
314 lines
12 KiB
Perl
# Common hooks library
|
|
package Devscripts::Salsa::Hooks;
|
|
|
|
use strict;
|
|
use Devscripts::Output;
|
|
use Moo::Role;
|
|
|
|
sub add_hooks {
|
|
my ($self, $repo_id, $repo) = @_;
|
|
if ( $self->config->kgb
|
|
or $self->config->disable_kgb
|
|
or $self->config->tagpending
|
|
or $self->config->disable_tagpending
|
|
or $self->config->irker
|
|
or $self->config->disable_irker
|
|
or $self->config->email
|
|
or $self->config->disable_email) {
|
|
my $hooks = $self->enabled_hooks($repo_id);
|
|
return 1 unless (defined $hooks);
|
|
# KGB hook (IRC)
|
|
if ($self->config->kgb or $self->config->disable_kgb) {
|
|
unless ($self->config->irc_channel->[0]
|
|
or $self->config->disable_kgb) {
|
|
ds_warn "--kgb needs --irc-channel";
|
|
return 1;
|
|
}
|
|
if ($self->config->irc_channel->[1]) {
|
|
ds_warn "KGB accepts only one --irc-channel value,";
|
|
}
|
|
if ($hooks->{kgb}) {
|
|
ds_warn "Deleting old kgb (was $hooks->{kgb}->{url})";
|
|
$self->api->delete_project_hook($repo_id, $hooks->{kgb}->{id});
|
|
}
|
|
if ($self->config->irc_channel->[0]
|
|
and not $self->config->disable_kgb) {
|
|
# TODO: if useful, add parameters for this options
|
|
eval {
|
|
$self->api->create_project_hook(
|
|
$repo_id,
|
|
{
|
|
url => $self->config->kgb_server_url
|
|
. $self->config->irc_channel->[0],
|
|
map { ($_ => 1) } @{ $self->config->kgb_options },
|
|
});
|
|
ds_verbose "KGB hook added to project $repo_id (channel: "
|
|
. $self->config->irc_channel->[0] . ')';
|
|
};
|
|
if ($@) {
|
|
ds_warn "Fail to add KGB hook: $@";
|
|
if (!$self->config->no_fail) {
|
|
ds_verbose "Use --no-fail to continue";
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# Irker hook (IRC)
|
|
if ($self->config->irker or $self->config->disable_irker) {
|
|
unless ($self->config->irc_channel->[0]
|
|
or $self->config->disable_irker) {
|
|
ds_warn "--irker needs --irc-channel";
|
|
return 1;
|
|
}
|
|
if ($hooks->{irker}) {
|
|
no warnings;
|
|
ds_warn
|
|
"Deleting old irker (redirected to $hooks->{irker}->{recipients})";
|
|
$self->api->delete_project_service($repo_id, 'irker');
|
|
}
|
|
if ($self->config->irc_channel->[0]
|
|
and not $self->config->disable_irker) {
|
|
# TODO: if useful, add parameters for this options
|
|
my $ch = join(' ',
|
|
map { '#' . $_ } @{ $self->config->irc_channel });
|
|
$self->api->edit_project_service(
|
|
$repo_id, 'irker',
|
|
{
|
|
active => 1,
|
|
server_host => $self->config->irker_host,
|
|
(
|
|
$self->config->irker_port
|
|
? (server_port => $self->config->irker_port)
|
|
: ()
|
|
),
|
|
default_irc_uri => $self->config->irker_server_url,
|
|
recipients => $ch,
|
|
colorize_messages => 1,
|
|
});
|
|
ds_verbose
|
|
"Irker hook added to project $repo_id (channel: $ch)";
|
|
}
|
|
}
|
|
# email on push
|
|
if ($self->config->email or $self->config->disable_email) {
|
|
if ($hooks->{email}) {
|
|
no warnings;
|
|
ds_warn
|
|
"Deleting old email-on-push (redirected to $hooks->{email}->{recipients})";
|
|
$self->api->delete_project_service($repo_id, 'emails-on-push');
|
|
}
|
|
if (@{ $self->config->email_recipient }
|
|
and not $self->config->disable_email) {
|
|
# TODO: if useful, add parameters for this options
|
|
$self->api->edit_project_service(
|
|
$repo_id,
|
|
'emails-on-push',
|
|
{
|
|
recipients => join(' ',
|
|
map { my $a = $_; $a =~ s/%p/$repo/; $a }
|
|
@{ $self->config->email_recipient }),
|
|
});
|
|
no warnings;
|
|
ds_verbose
|
|
"Email-on-push hook added to project $repo_id (recipients: "
|
|
. join(' ', @{ $self->config->email_recipient }) . ')';
|
|
}
|
|
}
|
|
# Tagpending hook
|
|
if ($self->config->tagpending or $self->config->disable_tagpending) {
|
|
if ($hooks->{tagpending}) {
|
|
ds_warn
|
|
"Deleting old tagpending (was $hooks->{tagpending}->{url})";
|
|
$self->api->delete_project_hook($repo_id,
|
|
$hooks->{tagpending}->{id});
|
|
}
|
|
my $repo_name = $self->api->project($repo_id)->{name};
|
|
unless ($self->config->disable_tagpending) {
|
|
eval {
|
|
$self->api->create_project_hook(
|
|
$repo_id,
|
|
{
|
|
url => $self->config->tagpending_server_url
|
|
. $repo_name,
|
|
push_events => 1,
|
|
});
|
|
ds_verbose "Tagpending hook added to project $repo_id";
|
|
};
|
|
if ($@) {
|
|
ds_warn "Fail to add Tagpending hook: $@";
|
|
if (!$self->config->no_fail) {
|
|
ds_verbose "Use --no-fail to continue";
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub enabled_hooks {
|
|
my ($self, $repo_id) = @_;
|
|
my $hooks;
|
|
my $res = {};
|
|
if ( $self->config->kgb
|
|
or $self->config->disable_kgb
|
|
or $self->config->tagpending
|
|
or $self->config->disable_tagpending) {
|
|
$hooks = eval { $self->api->project_hooks($repo_id) };
|
|
if ($@) {
|
|
ds_warn "Unable to check hooks for project $repo_id";
|
|
return undef;
|
|
}
|
|
foreach my $h (@{$hooks}) {
|
|
$res->{kgb} = {
|
|
id => $h->{id},
|
|
url => $h->{url},
|
|
options => [grep { $h->{$_} and $h->{$_} eq 1 } keys %$h],
|
|
}
|
|
if $h->{url} =~ /\Q$self->{config}->{kgb_server_url}\E/;
|
|
$res->{tagpending} = {
|
|
id => $h->{id},
|
|
url => $h->{url},
|
|
}
|
|
if $h->{url} =~ /\Q$self->{config}->{tagpending_server_url}\E/;
|
|
}
|
|
}
|
|
if ( ($self->config->email or $self->config->disable_email)
|
|
and $_ = $self->api->project_service($repo_id, 'emails-on-push')
|
|
and $_->{active}) {
|
|
$res->{email} = $_->{properties};
|
|
}
|
|
if ( ($self->config->irker or $self->config->disable_irker)
|
|
and $_ = $self->api->project_service($repo_id, 'irker')
|
|
and $_->{active}) {
|
|
$res->{irker} = $_->{properties};
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
sub _check_config {
|
|
my ($config, $key_name, $config_name, $can_be_private, $res_ref) = @_;
|
|
if (!$config) { return undef; }
|
|
for ($config) {
|
|
if ($can_be_private) {
|
|
if ($_ eq "private") {
|
|
push @$res_ref, $key_name => "private";
|
|
} elsif ($_ =~ qr/y(es)?|true|enabled?/) {
|
|
push @$res_ref, $key_name => "enabled";
|
|
} elsif ($_ =~ qr/no?|false|disabled?/) {
|
|
push @$res_ref, $key_name => "disabled";
|
|
} else {
|
|
print "error with SALSA_$config_name";
|
|
}
|
|
} else {
|
|
if ($_ =~ qr/y(es)?|true|enabled?/) {
|
|
push @$res_ref, $key_name => 1;
|
|
} elsif ($_ =~ qr/no?|false|disabled?/) {
|
|
push @$res_ref, $key_name => 0;
|
|
} else {
|
|
print "error with SALSA_$config_name";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub desc {
|
|
my ($self, $repo) = @_;
|
|
my @res = ();
|
|
if ($self->config->desc) {
|
|
my $str = $self->config->desc_pattern;
|
|
$str =~ s/%P/$repo/g;
|
|
$repo =~ s#.*/##;
|
|
$str =~ s/%p/$repo/g;
|
|
push @res, description => $str;
|
|
}
|
|
if ($self->config->build_timeout) {
|
|
push @res, build_timeout => $self->config->build_timeout;
|
|
}
|
|
if ($self->config->ci_config_path) {
|
|
push @res, ci_config_path => $self->config->ci_config_path;
|
|
}
|
|
|
|
# Parameter: config value, key name, config name, has private
|
|
_check_config($self->config->analytics,
|
|
"analytics_access_level", "ENABLE_ANALYTICS", 1, \@res);
|
|
_check_config($self->config->auto_devops,
|
|
"auto_devops_enabled", "ENABLE_AUTO_DEVOPS", 0, \@res);
|
|
_check_config(
|
|
$self->config->container,
|
|
"container_registry_access_level",
|
|
"ENABLE_CONTAINER", 1, \@res
|
|
);
|
|
_check_config($self->config->environments,
|
|
"environments_access_level", "ENABLE_ENVIRONMENTS", 1, \@res);
|
|
_check_config($self->config->feature_flags,
|
|
"feature_flags_access_level", "ENABLE_FEATURE_FLAGS", 1, \@res);
|
|
_check_config($self->config->forks, "forking_access_level",
|
|
"ENABLE_FORKS", 1, \@res);
|
|
_check_config($self->config->infrastructure,
|
|
"infrastructure_access_level", "ENABLE_INFRASTRUCTURE", 1, \@res);
|
|
_check_config($self->config->issues, "issues_access_level",
|
|
"ENABLE_ISSUES", 1, \@res);
|
|
# Renamed terminology, kept for legacy: jobs == builds_access_level (ENABLE_JOBS -> ENABLE_BUILD)
|
|
_check_config($self->config->jobs, "builds_access_level", "ENABLE_JOBS",
|
|
1, \@res);
|
|
_check_config($self->config->lfs, "lfs_enabled", "ENABLE_LFS", 0, \@res);
|
|
_check_config($self->config->mr, "merge_requests_access_level",
|
|
"ENABLE_MR", 1, \@res);
|
|
_check_config($self->config->monitor,
|
|
"monitor_access_level", "ENABLE_MONITOR", 1, \@res);
|
|
_check_config($self->config->packages,
|
|
"packages_enabled", "ENABLE_PACKAGES", 0, \@res);
|
|
_check_config($self->config->pages, "pages_access_level", "ENABLE_PAGES",
|
|
1, \@res);
|
|
_check_config($self->config->releases,
|
|
"releases_access_level", "ENABLE_RELEASES", 1, \@res);
|
|
_check_config(
|
|
$self->config->disable_remove_branch,
|
|
"remove_source_branch_after_merge",
|
|
"REMOVE_SOURCE_BRANCH", 0, \@res
|
|
);
|
|
_check_config($self->config->repo, "repository_access_level",
|
|
"ENABLE_REPO", 1, \@res);
|
|
_check_config($self->config->request_access,
|
|
"request_access_enabled", "REQUEST_ACCESS", 0, \@res);
|
|
_check_config($self->config->requirements,
|
|
"requirements_access_level", "ENABLE_REQUIREMENTS", 1, \@res);
|
|
_check_config(
|
|
$self->config->security_compliance,
|
|
"security_and_compliance_access_level",
|
|
"ENABLE_SECURITY_COMPLIANCE", 1, \@res
|
|
);
|
|
_check_config($self->config->service_desk,
|
|
"service_desk_enabled", "ENABLE_SERVICE_DESK", 0, \@res);
|
|
_check_config($self->config->snippets,
|
|
"snippets_access_level", "ENABLE_SNIPPETS", 1, \@res);
|
|
_check_config($self->config->wiki, "wiki_access_level", "ENABLE_WIKI", 1,
|
|
\@res);
|
|
|
|
return @res;
|
|
}
|
|
|
|
sub desc_multipart {
|
|
my ($self, $repo) = @_;
|
|
my @res = ();
|
|
if ($self->config->avatar_path) {
|
|
my $str = $self->config->avatar_path;
|
|
$str =~ s/%p/$repo/g;
|
|
unless (-r $str) {
|
|
ds_warn "Unable to find: $str";
|
|
unless ($self->config->no_fail) {
|
|
ds_verbose "Use --no-fail to continue";
|
|
exit 1;
|
|
}
|
|
} else {
|
|
# avatar_path (salsa) -> avatar (GitLab API)
|
|
push @res, avatar => $str;
|
|
}
|
|
}
|
|
return @res;
|
|
}
|
|
|
|
1;
|