예제 #1
0
 public function setUp()
 {
     $this->application = new Application();
     $this->context = Context::create($this->application);
     $this->informationCollector = $this->getMock("\\Liip\\RMT\\Information\\InformationCollector");
     $this->context->setService('information-collector', $this->informationCollector);
 }
예제 #2
0
 private function addGitFlowCommands(Context $context)
 {
     if (!$context->getVCS() instanceof VCS\Git) {
         return;
     }
     $this->add($this->createCommand("StartCommand"));
     $this->add($this->createCommand("HotfixCommand"));
     $this->add($this->createCommand("FinishCommand"));
 }
예제 #3
0
 /**
  * Returns the current context.
  * 
  * @return Context
  */
 protected function getContext()
 {
     if ($this->context === null) {
         $this->context = Context::create($this->getApplication());
     }
     return $this->context;
 }
예제 #4
0
 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 . ')');
 }
예제 #5
0
 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();
 }
예제 #6
0
 /**
  * {@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), '.');
 }
예제 #7
0
 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>');
     }
 }
 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);
 }
예제 #9
0
 /**
  * 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;
 }
예제 #10
0
 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();
 }
예제 #12
0
파일: BaseAction.php 프로젝트: liip/rmt
 /**
  * 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;
 }
예제 #13
0
 public function execute()
 {
     $newVersion = Context::getParam('new-version');
     $composerFile = Context::getParam('project-root') . '/composer.json';
     if (!file_exists($composerFile)) {
         throw new \Liip\RMT\Exception("Impossible to file the composer file ({$composerFile})");
     }
     $fileContent = file_get_contents($composerFile);
     $fileContent = preg_replace('/("version":[^,]*,)/', '"version": "' . $newVersion . '",', $fileContent);
     file_put_contents($composerFile, $fileContent);
     $this->confirmSuccess();
 }
예제 #14
0
 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();
 }
 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]);
 }
예제 #16
0
파일: ChangesCommand.php 프로젝트: liip/rmt
 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));
 }
예제 #17
0
파일: TestsCheck.php 프로젝트: liip/rmt
 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 . ')');
     }
 }
예제 #18
0
 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();
 }
예제 #19
0
 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();
 }
예제 #20
0
파일: CurrentCommand.php 프로젝트: liip/rmt
 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);
     }
 }
예제 #21
0
 /**
  * will update a given filename with the current version
  *
  * @param string $filename
  *
  * @throws \Liip\RMT\Exception
  */
 protected function updateFile($filename)
 {
     $current = Context::getParam('current-version');
     $next = Context::getParam('new-version');
     $content = file_get_contents($filename);
     if (false === strpos($content, $current)) {
         throw new Exception('The version class ' . $filename . " does not contain the current version {$current}");
     }
     if (isset($this->options['pattern'])) {
         $current = str_replace('%version%', $current, $this->options['pattern']);
         $next = str_replace('%version%', $next, $this->options['pattern']);
     }
     $content = str_replace($current, $next, $content);
     if (false === strpos($content, $next)) {
         throw new Exception('The version class ' . $filename . " could not be updated with version {$next}");
     }
     file_put_contents($filename, $content);
 }
예제 #22
0
 /**
  * Context factory method.
  * 
  * @param \Liip\RMT\Application $application
  * @return \Liip\RMT\Context
  */
 public static function create(Application $application)
 {
     $rootDir = $application->getProjectRootDir();
     $helper = new Helpers\ComposerConfig();
     $helper->setComposerFile($rootDir . '/composer.json');
     $config = $helper->getRMTConfigSection();
     $context = new Context();
     $builder = new Helpers\ServiceBuilder($context);
     /*
      * The following services are config-dependent
      */
     if ($config !== null) {
         if ($config->getVcs()) {
             $context->setService('vcs', $builder->getService($config->getVcs(), 'vcs'));
         }
         // Store the config for latter usage
         $context->setParameter('config', $config);
         /*
          * populate version persister
          */
         $context->setService("version-persister", $builder->getService($config->getVersionPersister(), 'versionPersister'));
         $context->setService("version-detector", $builder->getService($config->getVersionDetector(), 'versionDetector'));
         /*
          * popluate lists
          */
         foreach (array("prerequisites", self::PRERELEASE_LIST, "postReleaseActions") as $listName) {
             $context->createEmptyList($listName);
             foreach ($config->{$listName} as $service) {
                 $context->addToList($listName, $builder->getService($service, $listName));
             }
         }
     }
     // Provide the root dir as a context parameter
     $context->setParameter('project-root', $rootDir);
     return $context;
 }
 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();
 }
예제 #24
0
파일: CommandAction.php 프로젝트: liip/rmt
 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());
     }
 }
예제 #25
0
 /**
  * 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);
 }
예제 #26
0
 /**
  * A common method to confirm success to the user
  * 
  * @param string $msg
  */
 public function confirmSuccess($msg = 'OK')
 {
     $this->context->getOutput()->writeln('<info>' . $msg . '</info>');
 }
예제 #27
0
파일: BaseCommand.php 프로젝트: liip/rmt
 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 "Impossible to read the branch name";
         }
         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());
 }
예제 #28
0
 /**
  * Constructor.
  * 
  * @param \Liip\RMT\Context $context
  * @throws \Liip\RMT\Exception
  */
 public function __construct(Context $context = null)
 {
     if ($context !== null) {
         $this->setComposerFile($context->getParam('project-root') . '/composer.json');
     }
 }
예제 #29
0
 public function testGetVersionDetector()
 {
     $application = new \Liip\RMT\Application();
     $context = Context::create($application);
     $actual = $context->getVersionDetector();
     $this->assertInstanceOf("\\Liip\\RMT\\Version\\Detector\\DetectorInterface", $actual);
 }
예제 #30
0
 /**
  * Get current git tag
  *
  * @return string
  */
 private function getCurrentVersion()
 {
     /** @var Liip\RMT\Version\Persister\PersisterInterface $versionPersister */
     $versionPersister = Context::get('version-persister');
     return $versionPersister->getCurrentVersion();
 }