* initial commit
This commit is contained in:
commit
2cf81c493e
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea
|
||||||
|
vendor/
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2013-2019 Medvedev Anton
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
22
bin/automatique
Executable file
22
bin/automatique
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Symfony\Component\Console\Application;
|
||||||
|
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
|
||||||
|
|
||||||
|
/** @var ContainerInterface $container */
|
||||||
|
$container = require __DIR__ . '/../config/container.php';
|
||||||
|
/** @var Application $application */
|
||||||
|
$application = $container->get(Application::class);
|
||||||
|
|
||||||
|
$commands = $container->get('config')['console']['commands'];
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$application->add($container->get($command));
|
||||||
|
}
|
||||||
|
$lazyCommands = $container->get('config')['console']['lazy_commands'];
|
||||||
|
$lazyLoader = new ContainerCommandLoader($container, $lazyCommands);
|
||||||
|
$application->setCommandLoader($lazyLoader);
|
||||||
|
$application->run();
|
||||||
72
bin/build
Executable file
72
bin/build
Executable file
@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/* (c) Anton Medvedev <anton@medv.io>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
define('ROOT', realpath(__DIR__ . '/..'));
|
||||||
|
$opt = getopt('v::');
|
||||||
|
|
||||||
|
$version = 'dev-master';
|
||||||
|
if (array_key_exists('v', $opt)) {
|
||||||
|
$version = $opt['v'];
|
||||||
|
if (!preg_match('/^\d+\.\d+\.\d+(-[\d\w\.]+)?$/i', $version)) {
|
||||||
|
die("Version number must follow semantic versioning.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(ROOT);
|
||||||
|
exec('composer install --no-dev');
|
||||||
|
|
||||||
|
$pharName = "automatique.phar";
|
||||||
|
$pharFile = ROOT . '/' . $pharName;
|
||||||
|
|
||||||
|
if (file_exists($pharFile)) {
|
||||||
|
unlink($pharFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
$phar = new \Phar($pharFile, 0, $pharName);
|
||||||
|
$phar->setSignatureAlgorithm(\Phar::SHA1);
|
||||||
|
$phar->startBuffering();
|
||||||
|
|
||||||
|
$iterator = new RecursiveDirectoryIterator(ROOT, FilesystemIterator::SKIP_DOTS);
|
||||||
|
$iterator = new RecursiveCallbackFilterIterator($iterator, function (SplFileInfo $fileInfo) {
|
||||||
|
return !in_array($fileInfo->getBasename(), ['.git', 'Tests', 'test'], true);
|
||||||
|
});
|
||||||
|
$iterator = new RecursiveIteratorIterator($iterator);
|
||||||
|
$iterator = new CallbackFilterIterator($iterator, function (SplFileInfo $fileInfo) {
|
||||||
|
return in_array($fileInfo->getExtension(), ['php', 'exe'], true);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($iterator as $fileInfo) {
|
||||||
|
$file = str_replace(ROOT, '', $fileInfo->getRealPath());
|
||||||
|
|
||||||
|
echo "Add file: " . $file . "\n";
|
||||||
|
$phar->addFile($fileInfo->getRealPath(), $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add bin/dep file
|
||||||
|
$depContent = file_get_contents(ROOT . '/bin/automatique');
|
||||||
|
$depContent = str_replace("#!/usr/bin/php\n", '', $depContent);
|
||||||
|
$depContent = str_replace("'master'", "'$version'", $depContent);
|
||||||
|
$depContent = str_replace('__FILE__', 'str_replace("phar://", "", Phar::running())', $depContent);
|
||||||
|
$phar->addFromString('bin/automatique', $depContent);
|
||||||
|
|
||||||
|
$stub = <<<STUB
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
Phar::mapPhar('{$pharName}');
|
||||||
|
require 'phar://{$pharName}/bin/automatique';
|
||||||
|
__HALT_COMPILER();
|
||||||
|
STUB;
|
||||||
|
|
||||||
|
$phar->setStub($stub);
|
||||||
|
$phar->compressFiles(Phar::GZ);
|
||||||
|
$phar->stopBuffering();
|
||||||
|
unset($phar);
|
||||||
|
|
||||||
|
echo "$pharName was created successfully.\n";
|
||||||
48
bin/clear-config-cache.php
Normal file
48
bin/clear-config-cache.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Script for clearing the configuration cache.
|
||||||
|
*
|
||||||
|
* Can also be invoked as `composer clear-config-cache`.
|
||||||
|
*
|
||||||
|
* @see https://github.com/zendframework/zend-expressive-skeleton for the canonical source repository
|
||||||
|
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
|
||||||
|
* @license https://github.com/zendframework/zend-expressive-skeleton/blob/master/LICENSE.md New BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
chdir(__DIR__ . '/../');
|
||||||
|
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
$config = include 'config/config.php';
|
||||||
|
|
||||||
|
if (! isset($config['config_cache_path'])) {
|
||||||
|
echo "No configuration cache path found" . PHP_EOL;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! file_exists($config['config_cache_path'])) {
|
||||||
|
printf(
|
||||||
|
"Configured config cache file '%s' not found%s",
|
||||||
|
$config['config_cache_path'],
|
||||||
|
PHP_EOL
|
||||||
|
);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === unlink($config['config_cache_path'])) {
|
||||||
|
printf(
|
||||||
|
"Error removing config cache file '%s'%s",
|
||||||
|
$config['config_cache_path'],
|
||||||
|
PHP_EOL
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"Removed configured config cache file '%s'%s",
|
||||||
|
$config['config_cache_path'],
|
||||||
|
PHP_EOL
|
||||||
|
);
|
||||||
|
exit(0);
|
||||||
45
composer.json
Normal file
45
composer.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"name": "edvidan/automatique",
|
||||||
|
"description": "Workflow auto installer",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://none",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/deployphp/deployer/issues",
|
||||||
|
"source": "https://github.com/deployphp/deployer",
|
||||||
|
"docs": "https://deployer.org/docs"
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Dávid Danyi",
|
||||||
|
"email": "david.danyi@ericsson.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\": "src/App"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/dep"
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": "~7.2",
|
||||||
|
"doctrine/collections": "^1.6",
|
||||||
|
"phpseclib/phpseclib": "~2.0",
|
||||||
|
"symfony/console": "~4.0",
|
||||||
|
"symfony/process": "~4.0",
|
||||||
|
"symfony/yaml": "~4.0",
|
||||||
|
"zendframework/zend-component-installer": "^2.1.1",
|
||||||
|
"zendframework/zend-config-aggregator": "^1.0",
|
||||||
|
"zendframework/zend-json": "3.1.0",
|
||||||
|
"zendframework/zend-servicemanager": "^3.3",
|
||||||
|
"zendframework/zend-stdlib": "^3.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^6.4.3",
|
||||||
|
"roave/security-advisories": "dev-master"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort-packages": true
|
||||||
|
}
|
||||||
|
}
|
||||||
2629
composer.lock
generated
Normal file
2629
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
config/.gitignore
vendored
Normal file
1
config/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
development.config.php
|
||||||
2
config/autoload/.gitignore
vendored
Normal file
2
config/autoload/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
local.php
|
||||||
|
*.local.php
|
||||||
22
config/autoload/dependencies.global.php
Normal file
22
config/autoload/dependencies.global.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
// Provides application-wide services.
|
||||||
|
// We recommend using fully-qualified class names whenever possible as
|
||||||
|
// service names.
|
||||||
|
'dependencies' => [
|
||||||
|
// Use 'aliases' to alias a service name to another service. The
|
||||||
|
// key is the alias name, the value is the service to which it points.
|
||||||
|
'aliases' => [],
|
||||||
|
// Use 'invokables' for constructor-less services, or services that do
|
||||||
|
// not require arguments to the constructor. Map a service name to the
|
||||||
|
// class name.
|
||||||
|
'invokables' => [],
|
||||||
|
// Use 'factories' for services provided by callbacks/factory classes.
|
||||||
|
'factories' => [
|
||||||
|
Symfony\Component\Console\Application::class => App\ApplicationFactory::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
35
config/autoload/development.local.php.dist
Normal file
35
config/autoload/development.local.php.dist
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Development-only configuration.
|
||||||
|
*
|
||||||
|
* Put settings you want enabled when under development mode in this file, and
|
||||||
|
* check it into your repository.
|
||||||
|
*
|
||||||
|
* Developers on your team will then automatically enable them by calling on
|
||||||
|
* `composer development-enable`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Zend\Expressive\Container;
|
||||||
|
use Zend\Expressive\Middleware\ErrorResponseGenerator;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'dependencies' => [
|
||||||
|
'invokables' => [
|
||||||
|
],
|
||||||
|
'factories' => [
|
||||||
|
ErrorResponseGenerator::class => Container\WhoopsErrorResponseGeneratorFactory::class,
|
||||||
|
'Zend\Expressive\Whoops' => Container\WhoopsFactory::class,
|
||||||
|
'Zend\Expressive\WhoopsPageHandler' => Container\WhoopsPageHandlerFactory::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'whoops' => [
|
||||||
|
'json_exceptions' => [
|
||||||
|
'display' => true,
|
||||||
|
'show_trace' => true,
|
||||||
|
'ajax_only' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
12
config/autoload/local.php.dist
Normal file
12
config/autoload/local.php.dist
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Local configuration.
|
||||||
|
*
|
||||||
|
* Copy this file to `local.php` and change its settings as required.
|
||||||
|
* `local.php` is ignored by git and safe to use for local and sensitive data like usernames and passwords.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
];
|
||||||
39
config/config.php
Normal file
39
config/config.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Zend\ConfigAggregator\ArrayProvider;
|
||||||
|
use Zend\ConfigAggregator\ConfigAggregator;
|
||||||
|
use Zend\ConfigAggregator\PhpFileProvider;
|
||||||
|
|
||||||
|
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
|
||||||
|
// `config/autoload/local.php`.
|
||||||
|
$cacheConfig = [
|
||||||
|
'config_cache_path' => 'cache/config-cache.php',
|
||||||
|
];
|
||||||
|
|
||||||
|
$aggregator = new ConfigAggregator([
|
||||||
|
// Include cache configuration
|
||||||
|
new ArrayProvider($cacheConfig),
|
||||||
|
|
||||||
|
// Swoole config to overwrite some services (if installed)
|
||||||
|
class_exists(\Zend\Expressive\Swoole\ConfigProvider::class)
|
||||||
|
? \Zend\Expressive\Swoole\ConfigProvider::class
|
||||||
|
: function(){ return[]; },
|
||||||
|
|
||||||
|
// Default App module config
|
||||||
|
App\ConfigProvider::class,
|
||||||
|
|
||||||
|
// Load application config in a pre-defined order in such a way that local settings
|
||||||
|
// overwrite global settings. (Loaded as first to last):
|
||||||
|
// - `global.php`
|
||||||
|
// - `*.global.php`
|
||||||
|
// - `local.php`
|
||||||
|
// - `*.local.php`
|
||||||
|
new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
|
||||||
|
|
||||||
|
// Load development config if it exists
|
||||||
|
new PhpFileProvider(realpath(__DIR__) . '/development.config.php'),
|
||||||
|
], $cacheConfig['config_cache_path']);
|
||||||
|
|
||||||
|
return $aggregator->getMergedConfig();
|
||||||
14
config/container.php
Normal file
14
config/container.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Zend\ServiceManager\ServiceManager;
|
||||||
|
|
||||||
|
// Load configuration
|
||||||
|
$config = require __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
$dependencies = $config['dependencies'];
|
||||||
|
$dependencies['services']['config'] = $config;
|
||||||
|
|
||||||
|
// Build container
|
||||||
|
return new ServiceManager($dependencies);
|
||||||
30
config/development.config.php.dist
Normal file
30
config/development.config.php.dist
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* File required to allow enablement of development mode.
|
||||||
|
*
|
||||||
|
* For use with the zf-development-mode tool.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* $ composer development-disable
|
||||||
|
* $ composer development-enable
|
||||||
|
* $ composer development-status
|
||||||
|
*
|
||||||
|
* DO NOT MODIFY THIS FILE.
|
||||||
|
*
|
||||||
|
* Provide your own development-mode settings by editing the file
|
||||||
|
* `config/autoload/development.local.php.dist`.
|
||||||
|
*
|
||||||
|
* Because this file is aggregated last, it simply ensures:
|
||||||
|
*
|
||||||
|
* - The `debug` flag is _enabled_.
|
||||||
|
* - Configuration caching is _disabled_.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Zend\ConfigAggregator\ConfigAggregator;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'debug' => true,
|
||||||
|
ConfigAggregator::ENABLE_CACHE => false,
|
||||||
|
];
|
||||||
20
phpcs.xml.dist
Normal file
20
phpcs.xml.dist
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Expressive Skeleton coding standard">
|
||||||
|
<description>Expressive Skeleton coding standard</description>
|
||||||
|
|
||||||
|
<!-- display progress -->
|
||||||
|
<arg value="p"/>
|
||||||
|
<arg name="colors"/>
|
||||||
|
|
||||||
|
<!-- inherit rules from: -->
|
||||||
|
<rule ref="PSR2"/>
|
||||||
|
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||||
|
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
|
||||||
|
<properties>
|
||||||
|
<property name="ignoreBlankLines" value="false"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Paths to check -->
|
||||||
|
<file>src</file>
|
||||||
|
</ruleset>
|
||||||
17
phpunit.xml.dist
Normal file
17
phpunit.xml.dist
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
colors="true">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="App\\Tests">
|
||||||
|
<directory>./test</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||||
|
<directory suffix=".php">./src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
||||||
16
src/App/ApplicationFactory.php
Normal file
16
src/App/ApplicationFactory.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Symfony\Component\Console\Application;
|
||||||
|
|
||||||
|
class ApplicationFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): Application
|
||||||
|
{
|
||||||
|
return new Application('Application console');
|
||||||
|
}
|
||||||
|
}
|
||||||
82
src/App/Command/BuildPackage.php
Normal file
82
src/App/Command/BuildPackage.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Downloader\SCP;
|
||||||
|
use App\Service\Builder;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
|
use Symfony\Component\Console\Helper\Table;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class BuildPackage extends Command
|
||||||
|
{
|
||||||
|
use SharedStorage;
|
||||||
|
const NAME = "standalone:build-package";
|
||||||
|
|
||||||
|
/** @var Builder */
|
||||||
|
private $builder;
|
||||||
|
|
||||||
|
public function __construct(Builder $builder, Collection $storage)
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->sharedStorage = $storage;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName(self::NAME)
|
||||||
|
->setDescription('Build packages on remote host')
|
||||||
|
->addOption("host", null, InputOption::VALUE_REQUIRED, "", false)
|
||||||
|
->addOption("path", null, InputOption::VALUE_REQUIRED, "", false)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function saveToShared(string $name, $value)
|
||||||
|
{
|
||||||
|
$this->sharedStorage->set(sprintf("%s:%s", self::NAME, $name), $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$host = $input->getOption("host");
|
||||||
|
$path = $input->getOption("path");
|
||||||
|
if (!$host && !$path) {
|
||||||
|
throw new Exception("Missing arguments");
|
||||||
|
}
|
||||||
|
$this->saveToShared("host", $host);
|
||||||
|
$this->saveToShared("path", $path);
|
||||||
|
$output->writeln("<info>Building package:</info>");
|
||||||
|
// $helper = $this->getHelper('process');
|
||||||
|
// $tableSection = $output->section();
|
||||||
|
// $totalProgressSection = $output->section();
|
||||||
|
// $itemProgressSection = $output->section();
|
||||||
|
// $table = new Table($tableSection);
|
||||||
|
// $table->setHeaders([
|
||||||
|
// 'Title',
|
||||||
|
// 'Pages',
|
||||||
|
// 'Size',
|
||||||
|
// ]);
|
||||||
|
// $table->render();
|
||||||
|
// $totalProgress = new ProgressBar($totalProgressSection);
|
||||||
|
// $itemProgress = new ProgressBar($itemProgressSection);
|
||||||
|
$remotePackage = $this->builder->buildRemotePackage($host, $path);
|
||||||
|
$this->saveToShared("package", $remotePackage);
|
||||||
|
$downloader = new SCP();
|
||||||
|
$downloader->download(sprintf("%s:%s", $host, $remotePackage), ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/App/Command/BuildPackageFactory.php
Normal file
20
src/App/Command/BuildPackageFactory.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\Builder;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class BuildPackageFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): BuildPackage
|
||||||
|
{
|
||||||
|
/** @var Builder $builder */
|
||||||
|
$builder = $container->get(Builder::class);
|
||||||
|
$sharedStorage = $container->get(ArrayCollection::class);
|
||||||
|
return new BuildPackage($builder, $sharedStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/App/Command/ComplexTaskConfig.php
Normal file
63
src/App/Command/ComplexTaskConfig.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\ConfigProvider;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\ArrayInput;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class ComplexTaskConfig extends Command
|
||||||
|
{
|
||||||
|
/** @var ConfigProvider */
|
||||||
|
private $configProvider;
|
||||||
|
|
||||||
|
/** @var ArrayCollection */
|
||||||
|
private $sharedStorage;
|
||||||
|
|
||||||
|
public function __construct(ConfigProvider $configProvider, ArrayCollection $sharedStorage)
|
||||||
|
{
|
||||||
|
$this->configProvider = $configProvider;
|
||||||
|
$this->sharedStorage = $sharedStorage;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName('complex:task-config')
|
||||||
|
->setDescription('Build using task config');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$taskConfig = $this->configProvider->getTaskConfig();
|
||||||
|
$app = $this->getApplication();
|
||||||
|
foreach ($taskConfig as $task) {
|
||||||
|
$cmd = $app->find($task['command']);
|
||||||
|
$args = [
|
||||||
|
'command' => $task['command']
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($task['args']) && is_array($task['args'])) {
|
||||||
|
$args += $task['args'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($task['stored-args']) && is_array($task['stored-args'])) {
|
||||||
|
foreach ($task['stored-args'] as $key => $storedArg) {
|
||||||
|
$args[$key] = $this->sharedStorage->get($storedArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cmd->run(new ArrayInput($args), $output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/App/Command/ComplexTaskConfigFactory.php
Normal file
21
src/App/Command/ComplexTaskConfigFactory.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\ConfigProvider;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class ComplexTaskConfigFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): ComplexTaskConfig
|
||||||
|
{
|
||||||
|
/** @var ConfigProvider $configProvider */
|
||||||
|
$configProvider = $container->get(ConfigProvider::class);
|
||||||
|
/** @var ArrayCollection $builder */
|
||||||
|
$builder = $container->get(ArrayCollection::class);
|
||||||
|
return new ComplexTaskConfig($configProvider, $builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/App/Command/GenerateOnboardPackage.php
Normal file
57
src/App/Command/GenerateOnboardPackage.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\Builder;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class GenerateOnboardPackage extends Command
|
||||||
|
{
|
||||||
|
use SharedStorage;
|
||||||
|
const NAME = "standalone:generate-onboard-package";
|
||||||
|
|
||||||
|
/** @var Builder */
|
||||||
|
private $builder;
|
||||||
|
|
||||||
|
public function __construct(Builder $builder, Collection $storage)
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->sharedStorage = $storage;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName(self::NAME)
|
||||||
|
->setDescription('Gen onboard package')
|
||||||
|
->addOption("host", null, InputOption::VALUE_REQUIRED, "", false)
|
||||||
|
->addOption("package", null, InputOption::VALUE_REQUIRED, "", false)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$host = $input->getOption("host");
|
||||||
|
$package = $input->getOption("package");
|
||||||
|
if (!$host && !$package) {
|
||||||
|
throw new Exception("Missing arguments");
|
||||||
|
}
|
||||||
|
$this->saveToShared("host", $host);
|
||||||
|
$this->saveToShared("path", $package);
|
||||||
|
$output->writeln("<info>Generate onboard package:</info>");
|
||||||
|
$output->writeln("Got args: " . $input->getOption("host") . $input->getOption("package"));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/App/Command/GenerateOnboardPackageFactory.php
Normal file
20
src/App/Command/GenerateOnboardPackageFactory.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\Builder;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class GenerateOnboardPackageFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): GenerateOnboardPackage
|
||||||
|
{
|
||||||
|
/** @var Builder $builder */
|
||||||
|
$builder = $container->get(Builder::class);
|
||||||
|
$sharedStorage = $container->get(ArrayCollection::class);
|
||||||
|
return new GenerateOnboardPackage($builder, $sharedStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/App/Command/SharedStorage.php
Normal file
18
src/App/Command/SharedStorage.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
|
||||||
|
trait SharedStorage
|
||||||
|
{
|
||||||
|
/** @var Collection */
|
||||||
|
protected $sharedStorage;
|
||||||
|
|
||||||
|
protected function saveToShared(string $name, $value)
|
||||||
|
{
|
||||||
|
$this->sharedStorage->set(sprintf("%s:%s", self::NAME, $name), $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/App/ConfigProvider.php
Normal file
67
src/App/ConfigProvider.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use App\Command;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration provider for the App module
|
||||||
|
*
|
||||||
|
* @see https://docs.zendframework.com/zend-component-installer/
|
||||||
|
*/
|
||||||
|
class ConfigProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the configuration array
|
||||||
|
*
|
||||||
|
* To add a bit of a structure, each section is defined in a separate
|
||||||
|
* method which returns an array with its configuration.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __invoke() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'dependencies' => $this->getDependencies(),
|
||||||
|
'console' => $this->getConsole(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the container dependencies
|
||||||
|
*/
|
||||||
|
public function getDependencies() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'invokables' => [
|
||||||
|
ArrayCollection::class,
|
||||||
|
],
|
||||||
|
'factories' => [
|
||||||
|
Service\Builder::class => Service\BuilderFactory::class,
|
||||||
|
Service\ConfigProvider::class => Service\ConfigProviderFactory::class,
|
||||||
|
|
||||||
|
Command\BuildPackage::class => Command\BuildPackageFactory::class,
|
||||||
|
Command\ComplexTaskConfig::class => Command\ComplexTaskConfigFactory::class,
|
||||||
|
Command\GenerateOnboardPackage::class => Command\GenerateOnboardPackageFactory::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the templates configuration
|
||||||
|
*/
|
||||||
|
public function getConsole() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'commands' => [
|
||||||
|
Command\ComplexTaskConfig::class,
|
||||||
|
],
|
||||||
|
'lazy_commands' => [
|
||||||
|
Command\BuildPackage::NAME => Command\BuildPackage::class,
|
||||||
|
Command\GenerateOnboardPackage::NAME => Command\GenerateOnboardPackage::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/App/Downloader/DownloaderInterface.php
Normal file
9
src/App/Downloader/DownloaderInterface.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Downloader;
|
||||||
|
|
||||||
|
interface DownloaderInterface {
|
||||||
|
public function download(string $remote, string $local): string;
|
||||||
|
}
|
||||||
21
src/App/Downloader/SCP.php
Normal file
21
src/App/Downloader/SCP.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Downloader;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class SCP implements DownloaderInterface
|
||||||
|
{
|
||||||
|
public function download(string $remote, string $local): string
|
||||||
|
{
|
||||||
|
$process = new Process([
|
||||||
|
'scp',
|
||||||
|
$remote,
|
||||||
|
$local
|
||||||
|
]);
|
||||||
|
$process->run();
|
||||||
|
return $process->getOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/App/Runner/Local.php
Normal file
19
src/App/Runner/Local.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Runner;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class Local implements RunnerInterface
|
||||||
|
{
|
||||||
|
public function execute($command): string
|
||||||
|
{
|
||||||
|
$process = new Process([
|
||||||
|
$command
|
||||||
|
]);
|
||||||
|
$process->run();
|
||||||
|
return $process->getOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/App/Runner/RunnerInterface.php
Normal file
9
src/App/Runner/RunnerInterface.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Runner;
|
||||||
|
|
||||||
|
interface RunnerInterface {
|
||||||
|
public function execute($command): string;
|
||||||
|
}
|
||||||
31
src/App/Runner/SSH.php
Normal file
31
src/App/Runner/SSH.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Runner;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class SSH implements RunnerInterface
|
||||||
|
{
|
||||||
|
private $hostname;
|
||||||
|
|
||||||
|
public function __construct($hostname)
|
||||||
|
{
|
||||||
|
$this->hostname = $hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute($command): string
|
||||||
|
{
|
||||||
|
$process = new Process([
|
||||||
|
'ssh',
|
||||||
|
$this->hostname,
|
||||||
|
$command
|
||||||
|
]);
|
||||||
|
$process->run();
|
||||||
|
if (!$process->isSuccessful()) {
|
||||||
|
throw new \Exception("Command failed with: " . $process->getErrorOutput());
|
||||||
|
}
|
||||||
|
return $process->getOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/App/Service/Builder.php
Normal file
27
src/App/Service/Builder.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Runner\SSH;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Builder
|
||||||
|
{
|
||||||
|
const PACKAGE_BUILDER_SCRIPT = "prepare_package.sh";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $host
|
||||||
|
* @param $path
|
||||||
|
* @return string Generated filename on remote host
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function buildRemotePackage($host, $path): string
|
||||||
|
{
|
||||||
|
$runner = new SSH($host);
|
||||||
|
$out = $runner->execute(sprintf("%s/%s", $path, self::PACKAGE_BUILDER_SCRIPT));
|
||||||
|
$lines = explode("\n", trim($out));
|
||||||
|
return array_pop($lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/App/Service/BuilderFactory.php
Normal file
15
src/App/Service/BuilderFactory.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class BuilderFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): Builder
|
||||||
|
{
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/App/Service/ConfigProvider.php
Normal file
65
src/App/Service/ConfigProvider.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
|
class ConfigProvider
|
||||||
|
{
|
||||||
|
const CONFIG_DIR = "automatique";
|
||||||
|
|
||||||
|
private $taskFile = "automatique.task.yaml";
|
||||||
|
private $envFile = "automatique.env.yaml";
|
||||||
|
|
||||||
|
private $loadOrder = [];
|
||||||
|
|
||||||
|
public function __construct(?string $taskOverride, ?string $envOverride)
|
||||||
|
{
|
||||||
|
if ($taskOverride) {
|
||||||
|
$this->taskFile = $taskOverride;
|
||||||
|
}
|
||||||
|
if ($envOverride) {
|
||||||
|
$this->envFile = $envOverride;
|
||||||
|
}
|
||||||
|
$this->loadOrder[] = ".";
|
||||||
|
$userCfgDir = sprintf("%s/.config/%s", $_SERVER['HOME'], self::CONFIG_DIR);
|
||||||
|
if (file_exists($userCfgDir)) {
|
||||||
|
$this->loadOrder[] = $userCfgDir;
|
||||||
|
}
|
||||||
|
$globalCfgDir = sprintf("/etc/%s", self::CONFIG_DIR);
|
||||||
|
if (file_exists($globalCfgDir)) {
|
||||||
|
$this->loadOrder[] = $globalCfgDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findConfigFile($filename): string
|
||||||
|
{
|
||||||
|
foreach ($this->loadOrder as $loadDir) {
|
||||||
|
$configFile = "${loadDir}/${filename}";
|
||||||
|
if (file_exists($configFile)) {
|
||||||
|
return $configFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException("Couldn't locate $filename");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readConfigFile($configFile): ?iterable
|
||||||
|
{
|
||||||
|
$configFile = $this->findConfigFile($configFile);
|
||||||
|
return Yaml::parseFile($configFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnvironmentConfig(): ?iterable
|
||||||
|
{
|
||||||
|
return $this->readConfigFile($this->envFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTaskConfig(): ?iterable
|
||||||
|
{
|
||||||
|
return $this->readConfigFile($this->taskFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/App/Service/ConfigProviderFactory.php
Normal file
25
src/App/Service/ConfigProviderFactory.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
|
||||||
|
class ConfigProviderFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): ConfigProvider
|
||||||
|
{
|
||||||
|
$taskFile = null;
|
||||||
|
$envFile = null;
|
||||||
|
$args = new ArgvInput();
|
||||||
|
if ($args->hasOption("env-file")) {
|
||||||
|
$envFile = $args->getOption("env-file");
|
||||||
|
}
|
||||||
|
if ($args->hasOption("task-file")) {
|
||||||
|
$taskFile = $args->getOption("task-file");
|
||||||
|
}
|
||||||
|
return new ConfigProvider($taskFile, $envFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user