Implement system for user packages in composer (#13718)

This commit is contained in:
Jellyfrog 2022-02-02 17:33:23 +01:00 committed by GitHub
parent 2dcc70301c
commit fdebee86b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 200 additions and 17 deletions

1
.gitignore vendored
View File

@ -29,6 +29,7 @@ patches
npm-debug.log
yarn-error.log
composer.phar
composer.plugins.json
_ide_helper.php
_ide_helper_models.php
resources/views/menu/custom.blade.php

View File

@ -63,6 +63,58 @@ class ComposerHelper
{
}
public static function addPlugin(string $package, string $version = null): int
{
$package = escapeshellarg($package . ($version ? ":$version" : null));
$cmds = [
'COMPOSER=composer.plugins.json ' . PHP_BINARY . " ./scripts/composer_wrapper.php require --no-update $package",
];
return self::exec($cmds);
}
public static function addPackage(string $package, string $version = null): int
{
$package = escapeshellarg($package . ($version ? ":$version" : null));
$cmds = [
'FORCE=1 ' . PHP_BINARY . " ./scripts/composer_wrapper.php require --update-no-dev $package",
];
return self::exec($cmds);
}
public static function removePlugin(string $package): int
{
$package = escapeshellarg($package);
$cmds = [
'COMPOSER=composer.plugins.json ' . PHP_BINARY . " ./scripts/composer_wrapper.php remove --no-update $package",
];
return self::exec($cmds);
}
public static function removePackage(string $package): int
{
$package = escapeshellarg($package);
$cmds = [
'FORCE=1 ' . PHP_BINARY . " ./scripts/composer_wrapper.php remove --update-no-dev $package",
];
return self::exec($cmds);
}
public static function getPlugins(): array
{
$plugins = is_file('composer.plugins.json') ?
json_decode(file_get_contents('composer.plugins.json'), true) : [];
return $plugins['require'] ?? [];
}
/**
* Initially populate .env file
*/
@ -120,9 +172,11 @@ class ComposerHelper
*
* @param string|array $cmds
*/
private static function exec($cmds)
private static function exec($cmds): int
{
$cmd = "set -v\n" . implode(PHP_EOL, (array) $cmds);
passthru($cmd);
passthru($cmd, $result_code);
return $result_code;
}
}

View File

@ -28,6 +28,7 @@ namespace LibreNMS\Validations;
use DateTime;
use DateTimeZone;
use Exception;
use LibreNMS\ComposerHelper;
use LibreNMS\Config;
use LibreNMS\Util\EnvHelper;
use LibreNMS\Util\Git;
@ -101,12 +102,17 @@ class Updates extends BaseValidation
$modifiedcmd = 'git diff --name-only --exit-code';
$validator->execAsUser($modifiedcmd, $cmdoutput, $code);
if ($code !== 0 && ! empty($cmdoutput)) {
$result = ValidationResult::warn(
'Your local git contains modified files, this could prevent automatic updates.',
'You can fix this with ./scripts/github-remove'
);
$result->setList('Modified Files', $cmdoutput);
$validator->result($result);
// Check so it's not only plugins that "pests" the diff
if (! ($cmdoutput === ['composer.json', 'composer.lock'] && ComposerHelper::getPlugins())) {
$result = ValidationResult::warn(
'Your local git contains modified files, this could prevent automatic updates.',
'You can fix this with ./scripts/github-remove'
);
$result->setList('Modified Files', $cmdoutput);
$validator->result($result);
}
}
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use LibreNMS\ComposerHelper;
class PluginAddCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'plugin:add {package} {version?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Install a plugin';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// Add package to "real" composer.json first, to catch dependency failures etc.
if (ComposerHelper::addPackage($this->argument('package'), $this->argument('version')) == 0) {
return ComposerHelper::addPlugin($this->argument('package'), $this->argument('version'));
}
return 1;
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use LibreNMS\ComposerHelper;
class PluginRemoveCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'plugin:remove {package}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Remove an installed plugin';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// Remove package from plugin first
// in case of failure, daily.sh should then be able to cleanup and leftover mess.
ComposerHelper::removePlugin($this->argument('package'));
ComposerHelper::removePackage($this->argument('package'));
return 0;
}
}

View File

@ -14,10 +14,6 @@ use LibreNMS\Config;
use LibreNMS\Util\Debug;
use LibreNMS\Validations\Php;
$init_modules = ['alerts'];
require __DIR__ . '/includes/init.php';
include_once __DIR__ . '/includes/notifications.php';
$options = getopt('df:o:t:r:');
if (isset($options['d'])) {
@ -25,6 +21,31 @@ if (isset($options['d'])) {
Debug::set();
}
/**
* Scripts without dependencies
*/
if ($options['f'] === 'composer_get_plugins') {
$output = [];
$plugins = is_file('composer.plugins.json') ?
json_decode(file_get_contents('composer.plugins.json')) : [];
foreach ($plugins->require ?? [] as $package => $version) {
$output[] = "$package:$version";
}
echo implode(' ', $output);
return;
}
/**
* Scripts with dependencies
*/
$init_modules = ['alerts'];
require __DIR__ . '/includes/init.php';
include_once __DIR__ . '/includes/notifications.php';
if ($options['f'] === 'update') {
if (! Config::get('update')) {
exit(0);

View File

@ -286,6 +286,9 @@ main () {
check_dependencies
php_ver_ret=$?
# Restore composer files if user installed plugins
git checkout --quiet -- composer.json composer.lock
update_res=0
if [[ "$up" == "1" ]] || [[ "$php_ver_ret" == "1" ]]; then
# Update current branch to latest
@ -343,6 +346,13 @@ main () {
# re-check dependencies after pull with the new code
check_dependencies
# Insert user installed plugins before calling composer install
PLUGINS=$(call_daily_php "composer_get_plugins")
if [ -n "$PLUGINS" ]; then
# shellcheck disable=SC2086
FORCE=1 ${COMPOSER} require --update-no-dev --no-install $PLUGINS
fi
status_run 'Updating Composer packages' "${COMPOSER} install --no-dev" 'update'
# Check if we need to revert (Must be in post pull so we can update it)

View File

@ -1635,11 +1635,6 @@ parameters:
count: 1
path: LibreNMS/Component.php
-
message: "#^Method LibreNMS\\\\ComposerHelper\\:\\:exec\\(\\) has no return type specified\\.$#"
count: 1
path: LibreNMS/ComposerHelper.php
-
message: "#^Method LibreNMS\\\\ComposerHelper\\:\\:populateEnv\\(\\) has no return type specified\\.$#"
count: 1