public function loadContext() { $configHandler = new Handler($this->getApplication()->getConfig(), $this->getApplication()->getProjectRootDir()); $config = $configHandler->getBaseConfig(); // Select a branch specific config if a VCS is in use if (isset($config['vcs'])) { Context::getInstance()->setService('vcs', $config['vcs']['class'], $config['vcs']['options']); /** @var VCSInterface $vcs */ $vcs = Context::get('vcs'); try { $branch = $vcs->getCurrentBranch(); } catch (\Exception $e) { echo "[31mImpossible to read the branch name[37m"; } if (isset($branch)) { $config = $configHandler->getConfigForBranch($branch); } } // Store the config for latter usage Context::getInstance()->setParameter('config', $config); // Populate the context foreach (array('version-generator', 'version-persister') as $service) { Context::getInstance()->setService($service, $config[$service]['class'], $config[$service]['options']); } foreach (array('prerequisites', 'pre-release-actions', 'post-release-actions') as $listName) { Context::getInstance()->createEmptyList($listName); foreach ($config[$listName] as $service) { Context::getInstance()->addToList($listName, $service['class'], $service['options']); } } // Provide the root dir as a context parameter Context::getInstance()->setParameter('project-root', $this->getApplication()->getProjectRootDir()); }
public function execute() { // Handle the skip option if (Context::get('information-collector')->getValueFor(self::SKIP_OPTION)) { Context::get('output')->writeln('<error>composer minimum-stability check skipped</error>'); return; } // file exists? if (!file_exists('composer.json')) { Context::get('output')->writeln('<error>composer.json does not exist, skipping check</error>'); return; } // if file is not readable, we can't perform our check if (!is_readable('composer.json')) { throw new \Exception('composer.json can not be read (permissions?), (you can force a release with option --' . self::SKIP_OPTION . ')'); } $contents = json_decode(file_get_contents('composer.json'), true); // fail if the composer config falls back to default, and this check has something else but default set if (!isset($contents['minimum-stability']) && $this->options['stability'] != 'stable') { throw new \Exception('minimum-stability is not set, but RMT config requires: ' . $this->options['stability'] . ' (you can force a release with option --' . self::SKIP_OPTION . ')'); } // fail if stability is set and not the one expected if (isset($contents['minimum-stability']) && $contents['minimum-stability'] != $this->options['stability']) { throw new \Exception('minimum-stability is set to: ' . $contents['minimum-stability'] . ', but RMT config requires: ' . $this->options['stability'] . ' (you can force a release with option --' . self::SKIP_OPTION . ')'); } $this->confirmSuccess(); }
public function execute() { // Handle the skip option if (Context::get('information-collector')->getValueFor(self::SKIP_OPTION)) { Context::get('output')->writeln('<error>composer security check skipped</error>'); return; } Context::get('output')->writeln('<comment>running composer security check</comment>'); // run the actual security check $checker = new SecurityChecker(); $alerts = $checker->check('composer.lock'); // exit succesfull if everything is fine if (count($alerts) == 0) { $this->confirmSuccess(); return; } // print out the advisories if available foreach ($alerts as $package => $alert) { Context::get('output')->writeln("<options=bold>{$package}</options=bold> {$alert['version']}"); foreach ($alert['advisories'] as $data) { Context::get('output')->writeln(''); Context::get('output')->writeln($data['title']); Context::get('output')->writeln($data['link']); Context::get('output')->writeln(''); } } // throw exception to have check fail throw new \Exception('composer.lock contains insecure packages (you can force a release with option --' . self::SKIP_OPTION . ')'); }
/** * {@inheritdoc} * * @throws \InvalidArgumentException */ public function generateNextVersion($currentVersion) { $type = isset($this->options['type']) ? $this->options['type'] : Context::get('information-collector')->getValueFor('type'); $label = 'none'; if (isset($this->options['allow-label']) && $this->options['allow-label'] == true) { $label = isset($this->options['label']) ? $this->options['label'] : Context::get('information-collector')->getValueFor('label'); } // Type validation $validTypes = array('patch', 'minor', 'major'); if (!in_array($type, $validTypes)) { throw new \InvalidArgumentException('The option [type] must be one of: {' . implode($validTypes, ', ') . "}, \"{$type}\" given"); } if (!preg_match('#^' . $this->getValidationRegex() . '$#', $currentVersion)) { throw new \Exception('Current version format is invalid (' . $currentVersion . '). It should be major.minor.patch'); } $matches = null; preg_match('$(?:(\\d+\\.\\d+\\.\\d+)(?:(-)([a-zA-Z]+)(\\d+)?)?)$', $currentVersion, $matches); // if last version is with label if (count($matches) > 3) { list($major, $minor, $patch) = explode('.', $currentVersion); $patch = substr($patch, 0, strpos($patch, '-')); if ($label != 'none') { // increment label if (array_key_exists(3, $matches)) { $oldLabel = $matches[3]; $labelVersion = 2; // if label is new clear version if ($label !== $oldLabel) { $labelVersion = false; } elseif (array_key_exists(4, $matches)) { // if version exists increment it $labelVersion = intval($matches[4]) + 1; } } return implode(array($major, $minor, $patch), '.') . '-' . $label . $labelVersion; } return implode(array($major, $minor, $patch), '.'); } list($major, $minor, $patch) = explode('.', $currentVersion); // Increment switch ($type) { case 'major': $major += 1; $patch = $minor = 0; break; case 'minor': $minor += 1; $patch = 0; break; default: $patch += 1; break; } // new label if ($label != 'none') { return implode(array($major, $minor, $patch), '.') . '-' . $label; } return implode(array($major, $minor, $patch), '.'); }
public function execute() { $directory = trim(shell_exec('pwd')); $username = Context::get('information-collector')->getValueFor('ter-username'); $password = Context::get('information-collector')->getValueFor('ter-password'); $comment = Context::get('information-collector')->getValueFor('ter-comment'); $uploader = new \NamelessCoder\TYPO3RepositoryClient\Uploader(); $uploader->upload($directory, $username, $password, $comment); }
public function execute() { try { Context::get('output')->writeEmptyLine(); Context::get('output')->writeln(Context::get('vcs')->getAllModificationsSince(Context::get('version-persister')->getCurrentVersionTag())); } catch (\Exception $e) { Context::get('output')->writeln('<error>No modification found: ' . $e->getMessage() . '</error>'); } }
/** * Return the remote name where to publish or null if not defined * * @return string|null */ protected function getRemote() { if ($this->options['ask-remote-name']) { return Context::get('information-collector')->getValueFor('remote'); } if ($this->options['remote-name'] !== null) { return $this->options['remote-name']; } return; }
public function execute() { /** @var VCSInterface $vcs */ $vcs = Context::get('vcs'); if (count($vcs->getLocalModifications()) == 0) { Context::get('output')->writeln('<error>No modification found, aborting commit</error>'); return; } $vcs->saveWorkingCopy(str_replace('%version%', Context::getParam('new-version'), $this->options['commit-message'])); $this->confirmSuccess(); }
public function execute() { $newVersion = Context::getParam('new-version'); // newscoop/library/Newscoop/Version.php $appFile = realpath(__DIR__ . '/../src/SWP/Bundle/CoreBundle/Version/Version.php'); Context::get('output')->writeln("Updating version [<yellow>{$newVersion}</yellow>] in {$appFile}: "); $fileContent = file_get_contents($appFile); $fileContent = preg_replace('/(.*protected \\$version = .*;)/', ' protected $version = \'' . $newVersion . '\';', $fileContent); $fileContent = preg_replace('/(.*protected \\$releaseDate = .*;)/', ' protected $releaseDate = \'' . date('Y-m-d') . '\';', $fileContent); file_put_contents($appFile, $fileContent); $this->confirmSuccess(); }
/** * Execute a command and render the output through the classical indented output * @param string $cmd * @param float|null $timeout * @return Process */ public function executeCommandInProcess($cmd, $timeout = null) { Context::get('output')->write("<comment>{$cmd}</comment>\n\n"); $process = new Process($cmd); if ($timeout !== null) { $process->setTimeout($timeout); } $process->run(function ($type, $buffer) { Context::get('output')->write($buffer); }); return $process; }
public function execute() { $versioner = new \NamelessCoder\TYPO3RepositoryClient\Versioner(); $directory = trim(shell_exec('pwd')); $version = $versioner->read('.'); $version[0] = Context::getParam('new-version'); try { $version[1] = Context::getParam('stability'); } catch (\InvalidArgumentException $e) { $version[1] = Context::get('information-collector')->getValueFor('stability'); } $versioner->write($directory, $version[0], $version[1]); }
public function execute() { // Allow to be skipped when explicitly activated from the config if ($this->options['allow-ignore'] && Context::get('information-collector')->getValueFor($this->ignoreCheckOptionName)) { Context::get('output')->writeln('<error>requested to be ignored</error>'); return; } $modCount = count(Context::get('vcs')->getLocalModifications()); if ($modCount > 0) { throw new \Exception('Your working directory contains ' . $modCount . ' local modifications. Use the --' . $this->ignoreCheckOptionName . " option to bypass this check.\n" . 'WARNING, if your release task include a commit action, the pending changes are going to be included ' . 'in the release', self::EXCEPTION_CODE); } $this->confirmSuccess(); }
protected function execute(InputInterface $input, OutputInterface $output) { $lastVersion = Context::get('version-persister')->getCurrentVersionTag(); $noMerges = $input->getOption('exclude-merge-commits'); if ($input->getOption('files')) { $output->writeln("Here is the list of files changed since <green>{$lastVersion}</green>:"); $output->indent(); $output->writeln(array_keys(Context::get('vcs')->getModifiedFilesSince($lastVersion))); return; } $output->writeln("Here is the list of changes since <green>{$lastVersion}</green>:"); $output->indent(); $output->writeln(Context::get('vcs')->getAllModificationsSince($lastVersion, false, $noMerges)); }
public function execute() { // Handle the skip option if (Context::get('information-collector')->getValueFor(self::SKIP_OPTION)) { Context::get('output')->writeln('<error>tests skipped</error>'); return; } // Run the tests and live output with the standard output class $timeout = isset($this->options['timeout']) ? $this->options['timeout'] : null; $process = $this->executeCommandInProcess($this->options['command'], $timeout); // Break up if the result is not good if ($process->getExitCode() !== $this->options['expected_exit_code']) { throw new \Exception('Tests fails (you can force a release with option --' . self::SKIP_OPTION . ')'); } }
public function execute() { // Handle the skip option if (Context::get('information-collector')->getValueFor(self::SKIP_OPTION)) { Context::get('output')->writeln('<error>composer.json validation skipped</error>'); return; } // Run the validation and live output with the standard output class $process = $this->executeCommandInProcess($this->options['composer'] . ' validate'); // Break up if the result is not good if ($process->getExitCode() !== 0) { throw new \Exception('composer.json invalid (you can force a release with option --' . self::SKIP_OPTION . ')'); } $this->confirmSuccess(); }
public function execute() { // Handle the commits dump if ($this->options['dump-commits'] == true) { try { $extraLines = Context::get('vcs')->getAllModificationsSince(Context::get('version-persister')->getCurrentVersionTag(), false, $this->options['exclude-merge-commits']); $this->options['extra-lines'] = $extraLines; } catch (NoReleaseFoundException $e) { Context::get('output')->writeln('<error>No commits dumped as this is the first release</error>'); } unset($this->options['dump-commits']); } $manager = new ChangelogManager($this->options['file'], $this->options['format']); $manager->update(Context::getParam('new-version'), Context::get('information-collector')->getValueFor('comment'), array_merge(array('type' => Context::get('information-collector')->getValueFor('type', null)), $this->options)); $this->confirmSuccess(); }
protected function execute(InputInterface $input, OutputInterface $output) { $this->loadContext(); $version = Context::get('version-persister')->getCurrentVersion(); if ($input->getOption('vcs-tag')) { $vcsTag = Context::get('version-persister')->getCurrentVersionTag(); } if ($input->getOption('raw') == true) { $output->writeln($input->getOption('vcs-tag') ? $vcsTag : $version); } else { $msg = "Current release is: <green>{$version}</green>"; if ($input->getOption('vcs-tag')) { $msg .= " (VCS tag: <green>{$vcsTag}</green>)"; } $output->writeln($msg); } }
public function execute() { // Output for devs $newVersion = Context::getParam('new-version'); // newscoop/library/Newscoop/Version.php $appFile = realpath(__DIR__ . '/../library/Newscoop/Version.php'); Context::get('output')->writeln("New version [<yellow>{$newVersion}</yellow>] udpated into {$appFile}: "); $fileContent = file_get_contents($appFile); $fileContent = preg_replace('/(.*const VERSION = .*;)/', " const VERSION = '{$newVersion}';", $fileContent); file_put_contents($appFile, $fileContent); // newscoop/template_engine/classes/CampVersion.php $appFile = realpath(__DIR__ . '/../template_engine/classes/CampVersion.php'); Context::get('output')->writeln("New version [<yellow>{$newVersion}</yellow>] udpated into {$appFile}: "); $fileContent = file_get_contents($appFile); $fileContent = preg_replace('/(.*private \\$m_release = .*;)/', ' private $m_release = \'' . $newVersion . '\';', $fileContent); $fileContent = preg_replace('/(.*private \\$m_releaseDate = .*;)/', ' private $m_releaseDate = \'' . date('Y-m-d') . '\';', $fileContent); $fileContent = preg_replace('/(.*private \\$m_copyrightYear = .*;)/', ' private $m_copyrightYear = ' . date('Y') . ';', $fileContent); file_put_contents($appFile, $fileContent); $this->confirmSuccess(); }
public function execute() { $command = $this->options['cmd']; Context::get('output')->write("<comment>{$command}</comment>\n\n"); // Prepare a callback for live output $callback = null; if ($this->options['live_output'] == true) { $callback = function ($type, $buffer) { $decorator = array('', ''); if ($type == Process::ERR) { $decorator = array('<error>', '</error>'); } Context::get('output')->write($decorator[0] . $buffer . $decorator[1]); }; } // Run the process $process = new Process($command); $process->run($callback); // Break up if the result is not good if ($this->options['stop_on_error'] && $process->getExitCode() !== 0) { throw new \RuntimeException("Command [{$command}] exit with code " . $process->getExitCode()); } }
public function execute() { Context::get('vcs')->createTag(Context::get('vcs')->getTagFromVersion(Context::getParam('new-version'))); $this->confirmSuccess(); }
public function save($versionNumber) { $comment = Context::get('information-collector')->getValueFor('comment'); $type = Context::get('information-collector')->getValueFor('type', null); $this->changelogManager->update($versionNumber, $comment, array('type' => $type)); }
/** * Get current git tag * * @return string */ private function getCurrentVersion() { /** @var Liip\RMT\Version\Persister\PersisterInterface $versionPersister */ $versionPersister = Context::get('version-persister'); return $versionPersister->getCurrentVersion(); }
/** * Always executed, but first initialize and interact have already been called * * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { // Get the current version or generate a new one if the user has confirm that this is required try { $currentVersion = Context::get('version-persister')->getCurrentVersion(); } catch (\Liip\RMT\Exception\NoReleaseFoundException $e) { if (Context::get('information-collector')->getValueFor('confirm-first') == false) { throw $e; } $currentVersion = Context::get('version-generator')->getInitialVersion(); } Context::getInstance()->setParameter('current-version', $currentVersion); // Generate and save the new version number $newVersion = Context::get('version-generator')->generateNextVersion(Context::getParam('current-version')); Context::getInstance()->setParameter('new-version', $newVersion); $this->executeActionListIfExist('pre-release-actions'); $this->getOutput()->writeSmallTitle('Release process'); $this->getOutput()->indent(); $this->getOutput()->writeln("A new version named [<yellow>{$newVersion}</yellow>] is going to be released"); Context::get('version-persister')->save($newVersion); $this->getOutput()->writeln('Release: <green>Success</green>'); $this->getOutput()->unIndent(); $this->executeActionListIfExist('post-release-actions'); }
public function save($versionNumber) { $tagName = $this->getTagFromVersion($versionNumber); Context::get('output')->writeln("Creation of a new VCS tag [<yellow>{$tagName}</yellow>]"); $this->vcs->createTag($tagName); }
/** * @param array $options */ public function __construct($options = array()) { $this->vcs = Context::get('vcs'); }
/** * Determine and set the next release version. */ protected function setReleaseVersion() { try { $currentVersion = Context::get('version-persister')->getCurrentVersion(); } catch (\Exception $e) { $currentVersion = Context::get('version-generator')->getInitialVersion(); } $this->releaseVersion = Context::get('version-generator')->generateNextVersion($currentVersion); }