From 097582c4978a26ca8d74c4296f87108773fff13a Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Fri, 14 Nov 2025 12:02:34 +0100 Subject: [PATCH] Bug 25952: Skip invalid repositories when searching for plugins This patch prevents the end-user to get the ugly 500 "malformed JSON string" when something wrong happens with the plugin search. It happens currently in ktd with the plugin repos listed in $KOHA_CONF An error is reported to the UI Signed-off-by: Owen Leonard --- .../prog/en/modules/plugins/plugins-home.tt | 9 ++ plugins/plugins-home.pl | 117 ++++++++++-------- 2 files changed, 71 insertions(+), 55 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt index 0f60847ceb9..90ea09d696f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt @@ -85,6 +85,15 @@ [% END %] + [% IF search_errors %] +

Search errors

+
+ [% FOREACH error IN search_errors %] +
Cannot search repository [% error.repo.name | html %]: [% error.error | html %]
+ [% END %] +
+ [% END %] + [% IF search_results %]

Search results

diff --git a/plugins/plugins-home.pl b/plugins/plugins-home.pl index 1a67713e7c7..b46fe73a32e 100755 --- a/plugins/plugins-home.pl +++ b/plugins/plugins-home.pl @@ -23,6 +23,7 @@ use CGI qw ( -utf8 ); use JSON qw( from_json ); use LWP::Simple qw( get ); +use Try::Tiny; use Koha::Plugins; use C4::Auth qw( get_template_and_user ); @@ -63,7 +64,7 @@ if ($plugins_enabled) { $template->param( plugins_restricted => C4::Context->config('plugins_restricted') ); $template->param( can_search => C4::Context->config('plugin_repos') ? 1 : 0 ); - my @results; + my ( @results, @errors ); if ($plugin_search) { my $repos = C4::Context->config('plugin_repos'); @@ -73,68 +74,74 @@ if ($plugins_enabled) { } foreach my $r ( @{ $repos->{repo} } ) { - if ( $r->{service} eq 'github' ) { - my $url = - "https://api.github.com/search/repositories?q=$plugin_search+user:$r->{org_name}+in:name,description"; - my $response = from_json( get($url) ); - foreach my $result ( @{ $response->{items} } ) { - next unless $result->{name} =~ /^koha-plugin-/; - my $releases = $result->{url} . "/releases/latest"; - my $release_info = get($releases); - next unless $release_info; - my $release = from_json($release_info); - my $tag_name = $release->{tag_name}; - for my $asset ( @{ $release->{assets} } ) { - if ( $asset->{browser_download_url} =~ m/\.kpz$/ ) { - $result->{install_name} = $asset->{name}; - $result->{install_url} = $asset->{browser_download_url}; - $result->{tag_name} = $tag_name; + try { + if ( $r->{service} eq 'github' ) { + my $url = + "https://api.github.com/search/repositories?q=$plugin_search+user:$r->{org_name}+in:name,description"; + my $response = from_json( get($url) ); + foreach my $result ( @{ $response->{items} } ) { + next unless $result->{name} =~ /^koha-plugin-/; + my $releases = $result->{url} . "/releases/latest"; + my $release_info = get($releases); + next unless $release_info; + my $release = from_json($release_info); + my $tag_name = $release->{tag_name}; + for my $asset ( @{ $release->{assets} } ) { + if ( $asset->{browser_download_url} =~ m/\.kpz$/ ) { + $result->{install_name} = $asset->{name}; + $result->{install_url} = $asset->{browser_download_url}; + $result->{tag_name} = $tag_name; + } } + push( @results, { repo => $r, result => $result } ); } - push( @results, { repo => $r, result => $result } ); - } - } elsif ( $r->{service} eq 'gitlab' ) { - my $org_name = $r->{org_name}; - my $url = - "https://gitlab.com/api/v4/groups/$org_name/projects?with_issues_enabled=no\&with_merge_requests_enabled=no\&with_shared=no\&include_subgroups=yes\&search=koha-plugin+$plugin_search"; - my $response = from_json( get($url) ); - foreach my $result ( @{$response} ) { - next unless $result->{name} =~ /^koha-plugin-/; - my $project_id = $result->{id}; - my $description = $result->{description} // ''; - my $web_url = $result->{web_url}; - my $releases_url = "https://gitlab.com/api/v4/projects/$project_id/releases"; - my $releases_info = get($releases_url); - next unless $releases_info; - my @releases = @{ from_json($releases_info) }; - - if ( scalar @releases > 0 ) { - - # Pick the first one, the latest release - my $latest = $releases[0]; - my $name = $latest->{name}; - my $tag_name = $latest->{tag_name}; - my @links = @{ $latest->{assets}->{links} }; - my $url = $links[0]->{direct_asset_url}; - my @parts = split( '/', $url ); - my $filename = $parts[-1]; - next unless $url =~ m/\.kpz$/; - my $result = { - description => $description, - install_name => $filename, - install_url => $url, - html_url => $web_url, - name => $name, - tag_name => $tag_name, - }; - push @results, { repo => $r, result => $result }; + } elsif ( $r->{service} eq 'gitlab' ) { + my $org_name = $r->{org_name}; + my $url = + "https://gitlab.com/api/v4/groups/$org_name/projects?with_issues_enabled=no\&with_merge_requests_enabled=no\&with_shared=no\&include_subgroups=yes\&search=koha-plugin+$plugin_search"; + my $response = from_json( get($url) ); + foreach my $result ( @{$response} ) { + next unless $result->{name} =~ /^koha-plugin-/; + my $project_id = $result->{id}; + my $description = $result->{description} // ''; + my $web_url = $result->{web_url}; + my $releases_url = "https://gitlab.com/api/v4/projects/$project_id/releases"; + my $releases_info = get($releases_url); + next unless $releases_info; + my @releases = @{ from_json($releases_info) }; + + if ( scalar @releases > 0 ) { + + # Pick the first one, the latest release + my $latest = $releases[0]; + my $name = $latest->{name}; + my $tag_name = $latest->{tag_name}; + my @links = @{ $latest->{assets}->{links} }; + my $url = $links[0]->{direct_asset_url}; + my @parts = split( '/', $url ); + my $filename = $parts[-1]; + next unless $url =~ m/\.kpz$/; + my $result = { + description => $description, + install_name => $filename, + install_url => $url, + html_url => $web_url, + name => $name, + tag_name => $tag_name, + }; + push @results, { repo => $r, result => $result }; + } } } - } + } catch { + warn $_; + push @errors, { repo => $r, error => $_ }; + }; } $template->param( search_results => \@results, + search_errors => \@errors, search_term => $plugin_search, ); } -- 2.39.5