* 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