diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81b9258 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..72adcbf --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Christophe Coevoet + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bbddcf3 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# Managing your ignored parameters with Composer + +This tool allows you to manage your ignored parameters when running a composer +install or update. It wokrs when storing the parameters in a Yaml file under +a ``parameters`` key. + +## Usage + +In your root composer.json, adds the following: + +```json +{ + "require": { + "logsafe/composer-parameter-handler": "1.0.*" + }, + "scripts": { + "post-install-cmd": [ + "LogSafe\\ParameterHandler\\ScriptHandler::buildParameters" + ], + "post-update-cmd": [ + "LogSafe\\ParameterHandler\\ScriptHandler::buildParameters" + ] + }, + "extra": { + "logsafe-parameters": { + "file": "app/config/parameters.yml" + } + } +} +``` + +The ``app/config/parameters.yml`` will then be created or updated by the +composer script, to match the structure of the dist file ``app/config/parameters.yml.dist`` +by asking you the missing parameters. + +By default, the dist file is assumed to be in the same place than the parameters +file, suffixed by ``.dist``. This can be changed in the configuration: + +```json +{ + "extra": { + "logsafe-parameters": { + "file": "app/config/parameters.yml", + "dist-file": "app/config/parameters.dist.yml" + } + } +} +``` + +The script handler will ask you interactively for parameters which are missing +in the parameters file, using the value of the dist file as default value. +All prompted values are parsed as inline Yaml, to allow you to define ``true``, +``false``, ``null`` or numbers easily. +If composer is run in a non-interactive mode, the values of the dist file +will be used for missing parameters. + +## Using environment variables to set the parameters + +For your prod environment, using an interactive prompt may not be possible +when deploying. In this case, you can rely on environment variables to provide +the parameters. This is achieved by providing a map between environment variables +and the parameters they should fill: + +```json +{ + "extra": { + "logsafe-parameters": { + "env-map": { + "MY_FIRST_PARAM": "my_first_param", + "MY_SECOND_PARAM": "my_second_param" + } + } + } +} +``` + +If an environment variable is set, its value will always replace the value +set in the existing parameters file. + +As environment variables can only be strings, they are also parsed as inline +YAML values to allows specifying ``null``, ``false``, ``true`` or numbers +easily. diff --git a/ScriptHandler.php b/ScriptHandler.php new file mode 100644 index 0000000..e8cef0c --- /dev/null +++ b/ScriptHandler.php @@ -0,0 +1,115 @@ +getComposer()->getPackage()->getExtra(); + + if (empty($extras['logsafe-parameters']['file'])) { + throw new \InvalidArgumentException('The extra.logsafe-parameters.file setting is required to use this script handler.'); + } + + $realFile = $extras['logsafe-parameters']['file']; + + if (empty($extras['logsafe-parameters']['dist-file'])) { + $distFile = $realFile.'.dist'; + } else { + $distFile = $extras['logsafe-parameters']['dist-file']; + } + + if (!is_file($distFile)) { + throw new \InvalidArgumentException(sprintf('The dist file "%s" does not exist. Check your dist-file config or create it.')); + } + + $exists = is_file($realFile); + + $yamlParser = new Parser(); + $io = $event->getIO(); + + if ($exists) { + $io->write('Updating the parameters.yml file.'); + } else { + $io->write('Creating the parameters.yml file.'); + } + + // Find the expected params + $expectedValues = $yamlParser->parse(file_get_contents($distFile)); + if (!isset($expectedValues['parameters'])) { + throw new \InvalidArgumentException('The parameters.yml.dist file seems invalid.'); + } + $expectedParams = (array) $expectedValues['parameters']; + + // find the actual params + $actualValues = array('parameters' => array()); + if ($exists) { + $actualValues = array_merge($actualValues, $yamlParser->parse(file_get_contents($realFile))); + } + $actualParams = (array) $actualValues['parameters']; + + // Remove the outdated params + foreach ($actualParams as $key => $value) { + if (!array_key_exists($key, $expectedParams)) { + unset($actualParams[$key]); + } + } + + $envMap = empty($extras['logsafe-parameters']['env-map']) ? array() : (array) $extras['logsafe-parameters']['env-map']; + + // Add the params coming from the environment values + $actualParams = array_replace($actualParams, self::getEnvValues($envMap)); + + $actualParams = self::getParams($io, $expectedParams, $actualParams); + + file_put_contents($realFile, "# This file is auto-generated during the composer install\n" . Yaml::dump(array('parameters' => $actualParams))); + } + + private static function getEnvValues(array $envMap) + { + $params = array(); + foreach ($envMap as $env => $param) { + $value = getenv($env); + if ($value) { + $params[$param] = Inline::parse($value); + } + } + + return $params; + } + + private static function getParams(IOInterface $io, array $expectedParams, array $actualParams) + { + // Simply use the expectedParams value as default for the missing params. + if (!$io->isInteractive()) { + return array_replace($expectedParams, $actualParams); + } + + $isStarted = false; + + foreach ($expectedParams as $key => $message) { + if (array_key_exists($key, $actualParams)) { + continue; + } + + if (!$isStarted) { + $isStarted = true; + $io->write('Some parameters are missing. Please provide them.'); + } + + $default = Inline::dump($message); + $value = $io->ask(sprintf('%s (%s):', $key, $default), $default); + + $actualParams[$key] = Inline::parse($value); + } + + return $actualParams; + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..20d14f9 --- /dev/null +++ b/composer.json @@ -0,0 +1,30 @@ +{ + "name": "logsafe/composer-parameter-handler", + "description": "Composer script handling your ignored parameter file", + "keywords": ["parameters management"], + "homepage": "https://github.com/LogSafe/ParameterHandler", + "license": "MIT", + "authors": [ + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + "minimum-stability": "dev", + "require": { + "php": ">=5.3.3", + "symfony/yaml": ">=2.0,<2.3-dev" + }, + "require-dev": { + "composer/composer": "*" + }, + "autoload": { + "psr-0": { "LogSafe\\ParameterHandler": "" } + }, + "target-dir": "LogSafe/ParameterHandler", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +}