示例#1
0
    protected function configure()
    {
        $deployers = \GitDeployer\Deployers\BaseDeployer::getDeployersForHelp();
        $this->setName('init')->setDescription('Initializes a skeleton .deployerfile in your Git repository')->setHelp(<<<HELP
 The <info>%command.name%</info> command allows you to initialize a skeletion .deployefile in your repository.
 This file contains the information that Git-Deployer needs to deploy your project.
 
 A typical .deployerfile looks like this (remove comments, as they are not valid for JSON):

 {
    # The deployers to use. This version of Git-Deployer supports the following deployers:
    # <comment>{$deployers}</comment>
    "type": "docker",

    # The configurations object is used to specify multiple configurations
    "configurations": {

        # You can add an arbitrary number of configurations, with any names in this section
        "production": {

            # Each deployer has it's own configuration options, specify them here. In our "docker"
            # example, we could specify the DOCKER_HOST variable, for example
            "host": "tcp://127.0.0.1:2375",

            # In order to not save any passwords or private data into the .deployerfile, you can use
            # parameter substitution. These parameters will be asked on deploy by Git-Deployer:
            "supersecret": "%subsituteme%"
        },
        "staging": {

            # You can override properties from other configurations
            # example, we could specify the DOCKER_HOST variable, for example
            "host": "tcp://192.168.0.1:2375"
        }
    },

    # For overriding to be able to work, you need to specify an inheritance chain, like so:
    inheritance": ["staging", "production"],

    # If you have any parameter substitutions, add them here with a description, so that
    # the user deploying knows what to put in:
    "parameters": {
        "subsituteme": "Example param question description?"
    }
 }

 For a list of configuration options for each deployer, you can use the deploy command help,
 for example, for the Docker deployer you would type:
 <info>help deploy docker</info>

HELP
);
    }
示例#2
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $repository = $input->getArgument('repository');
     $revision = $input->getArgument('revision');
     $configuration = $input->getOption('configuration');
     $bag = $input->getOption('bag');
     $force = $input->getOption('force-redeploy');
     // -> Check that the revision matches what we expect
     preg_match('#^(tag|branch|rev):(.*)#iu', $revision, $matches);
     if (count($matches) < 3) {
         throw new \Exception('You must correctly specify the tag/branch/revision you want to deploy!' . "\n" . 'Check "help deploy" for an explanation.');
     } else {
         $type = $matches[1];
         $version = $matches[2];
     }
     // -> Get logged-in service
     $instance = \GitDeployer\AppInstance::getInstance();
     $appService = $instance->service();
     $appService->setInstances($input, $output, $this->getHelperSet());
     // .. and storage
     $storage = $instance->storage();
     $hasBeenFound = false;
     $this->showMessage('INIT', 'Getting repository...', $output);
     foreach ($appService->getProjects() as $key => $project) {
         if ($project->name() == $repository) {
             $hasBeenFound = true;
             $status = $storage->getDeploymentStatus($project);
             // -> Check if we have already been added to Git-Deployer yet
             if (!$status->added()) {
                 throw new \Exception('This repository is not yet added to Git-Deployer!' . "\n" . 'Please add it first via the add command.');
             }
             // -> Check we are not deploying the same version again. Ask
             // if we do, so the user can decide
             if ($status->isDeployd()) {
                 if ($status->getDeployedVersion() == $revision && !$force) {
                     $helper = $this->getHelper('question');
                     $question = new ConfirmationQuestion('Version ' . $status->getDeployedVersion() . ' was already deployed on ' . $status->deployedWhen() . '. Continue anyway? (y/[n]) ', false);
                     if (!$helper->ask($input, $output, $question)) {
                         break;
                     }
                 }
             }
             // -> Now clone it to a temp directory, if it doesn't exist already
             $tmpDir = sys_get_temp_dir() . '/git-deploy-' . strtolower($project->name());
             if (\Gitonomy\Git\Admin::isValidRepository($tmpDir)) {
                 $this->showMessage('GIT', 'Pulling latest changes from repository...', $output);
                 $repository = \Gitonomy\Git\Admin::init($tmpDir, false);
                 $repository->run('pull');
             } else {
                 $this->showMessage('GIT', 'Cloning repository...', $output);
                 $repository = \Gitonomy\Git\Admin::cloneTo($tmpDir, $project->url(), false);
             }
             // -> Check out the correct branch/revision/tag
             $this->showMessage('GIT', 'Checking out ' . $revision . '...', $output);
             $wc = $repository->getWorkingCopy();
             $wc->checkout($version);
             // -> Open .deployerfile and parse it
             $this->showMessage('DEPLOY', 'Checking .deployerfile...', $output);
             if (file_exists($tmpDir . '/.deployerfile')) {
                 $deployerfile = json_decode(file_get_contents($tmpDir . '/.deployerfile'));
             } else {
                 throw new \Exception('This repository has no .deployerfile!' . "\n" . 'Please add one first!');
             }
             if ($deployerfile == null) {
                 throw new \Exception('Could not parse .deployerfile: ' . json_last_error_msg() . "\n" . 'Please check that your JSON is valid!');
             }
             // -> Load the correct deployer from the .deployerfile, and fire it up with
             // the correct configuration options
             if (!isset($deployerfile->type)) {
                 throw new \Exception('Could not parse .deployerfile: ' . "\n" . 'Please specify a deployer via the "type" option!');
             }
             if (!isset($deployerfile->configurations) || isset($deployerfile->configurations) && !is_object($deployerfile->configurations)) {
                 throw new \Exception('Could not parse .deployerfile: ' . "\n" . 'Please specify at least one deployment configuration in the "configurations" option!');
             }
             // -> Get available configurations, and if not set, ask the user
             // which configuration to use
             $configs = get_object_vars($deployerfile->configurations);
             if ($configuration == null && count(get_object_vars($deployerfile->configurations)) > 1) {
                 // If no configuration has been specified via command line,
                 // ask the user which one to use
                 $confignames = array();
                 foreach ($configs as $name => $values) {
                     $confignames[] = $name;
                 }
                 // -> Get storage service to use
                 $question = new ChoiceQuestion('Which deployment configuration would you like to use?', $confignames);
                 $question->setValidator(function ($answer) use($configs, $confignames) {
                     if (!isset($configs[$confignames[$answer]])) {
                         throw new \RuntimeException('Please select a correct value!');
                     }
                     return $confignames[$answer];
                 });
                 $configuration = $helper->ask($input, $output, $question);
             } elseif ($configuration != null) {
                 // Try to use the current specified configuration
                 if (!isset($configs[$configuration])) {
                     throw new \Exception('The configuration "' . $configuration . '" was not found in this .deployefile!');
                 }
             } else {
                 foreach ($configs as $name => $values) {
                     $configuration = $name;
                 }
             }
             // -> Merge the current configuration inheritance chain, if any
             if (!isset($deployerfile->inheritance)) {
                 $mergedConfig = json_decode(json_encode($configs[$configuration]), true);
             } else {
                 $chain = $deployerfile->inheritance;
                 $minChainFound = false;
                 $smallerChain = array();
                 foreach ($chain as $key) {
                     if ($key == $configuration) {
                         $minChainFound = true;
                         $smallerChain[] = $key;
                     } else {
                         if ($minChainFound) {
                             $smallerChain[] = $key;
                         }
                     }
                 }
                 if (count($smallerChain) > 1) {
                     $mergedConfig = array();
                     foreach (array_reverse($smallerChain) as $configmerge) {
                         $mergedConfig = array_replace_recursive($mergedConfig, json_decode(json_encode($configs[$configmerge]), true));
                     }
                 } else {
                     $mergedConfig = json_decode(json_encode($configs[$smallerChain[0]]), true);
                 }
             }
             // -> Check if we have saved parameter bags, and offer the user
             // to choose one if so, or use the one provided from the command line
             $xdg = new \XdgBaseDir\Xdg();
             $bagPath = $xdg->getHomeConfigDir() . '/git-deployer';
             if ($bag != null) {
                 if (!file_exists($bagPath . '/' . $project->name() . '-' . $bag . '.bag')) {
                     throw new \Exception('This parameter bag has not been found!' . "\n" . 'Please check your naming!');
                 } else {
                     $answers = unserialize(file_get_contents($bagPath . '/' . $project->name() . '-' . $bag . '.bag'));
                 }
             } else {
                 $availableBags = array();
                 if (file_exists($bagPath)) {
                     $dh = opendir($bagPath);
                     while (($file = readdir($dh)) !== false) {
                         $fileInfo = pathinfo($file);
                         if ($fileInfo['extension'] == 'bag') {
                             if (stristr($fileInfo['filename'], $project->name())) {
                                 $availableBags[] = str_replace($project->name() . '-', '', $fileInfo['filename']);
                             }
                         }
                     }
                     closedir($dh);
                 }
                 if (count($availableBags) > 0) {
                     array_unshift($availableBags, "Don't use a bag");
                     $helper = $this->getHelper('question');
                     $question = new ChoiceQuestion('One or more parameter bags have been found. Which one do you want to use?', $availableBags);
                     $question->setValidator(function ($answer) use($availableBags) {
                         if ($answer == 0) {
                             return false;
                         }
                         if (!isset($availableBags[$answer])) {
                             throw new \RuntimeException('Please select a correct value!');
                         }
                         return $availableBags[$answer];
                     });
                     $parameterBag = $helper->ask($input, $output, $question);
                     if ($parameterBag) {
                         $answers = unserialize(file_get_contents($bagPath . '/' . $project->name() . '-' . $parameterBag . '.bag'));
                     } else {
                         $answers = array();
                     }
                 } else {
                     $answers = array();
                 }
             }
             // -> Replace placeholders in our config using parameter bags
             $bagModified = false;
             if (isset($deployerfile->parameters)) {
                 foreach ($deployerfile->parameters as $key => $questionhelp) {
                     if (!isset($answers[$key])) {
                         $helper = $this->getHelper('question');
                         $question = new Question($questionhelp . ' ');
                         $questionanswer = $helper->ask($input, $output, $question);
                         if ($questionanswer == null) {
                             $answers[$key] = '';
                         } else {
                             $answers[$key] = $questionanswer;
                         }
                         $bagModified = true;
                     }
                 }
                 // -> Ask the user to save this parameter bag
                 if ($bagModified) {
                     $helper = $this->getHelper('question');
                     $question = new ConfirmationQuestion('Do you want to save these answers in a parameter bag for next time? ([y]/n) ', true);
                     if ($helper->ask($input, $output, $question)) {
                         $question = new Question('Please provide a name for the new (or existing, will overwrite) parameter bag: ');
                         $question->setValidator(function ($answer) {
                             if (strlen($answer) < 1) {
                                 throw new \RuntimeException('Please provide a name for this parameter bag!');
                             } else {
                                 if (!preg_match('#\\w+#iu', $answer)) {
                                     throw new \RuntimeException('The name provided for this parameter bag is invalid!');
                                 }
                             }
                             return $answer;
                         });
                         $bagname = $helper->ask($input, $output, $question);
                         // -> Save this bag!
                         $xdg = new \XdgBaseDir\Xdg();
                         $savePath = $xdg->getHomeConfigDir() . '/git-deployer';
                         $saveFile = $savePath . '/' . $project->name() . '-' . $bagname . '.bag';
                         if (!file_exists($savePath)) {
                             mkdir($savePath);
                         }
                         file_put_contents($saveFile, serialize($answers));
                     }
                 }
                 // -> Now traverse the array to replace the values, and as such
                 // get our merged config ready to pass it into the deployer
                 $replacedConfig = $this->replacePlaceholders($mergedConfig, $answers);
             }
             // -> Execute the requested deployer with our merged configuration array
             $deployer = \GitDeployer\Deployers\BaseDeployer::createServiceInstance(ucwords($deployerfile->type), $input, $output, $this->getHelperSet());
             list($statusok, $trace) = $deployer->deploy($project, $tmpDir, $replacedConfig);
             // -> Check if the deployment went well, return any errors,
             // or update the deployment status for the project otherwise
             if ($statusok) {
                 $status->deployedWhen(date('c'));
                 $status->deployedType($type);
                 $status->deployedString($version);
                 $storage->setDeploymentStatus($project, $status);
             } else {
                 $output->writeln($trace);
                 throw new \Exception('Deployment did not completely finish! See trace above.');
             }
             // -> Finish up!
             $this->showMessage('FINISH', '<info>Done!</info>', $output);
             break;
         }
     }
     if (!$hasBeenFound) {
         throw new \Exception('Project "' . $repository . '" could not be found! Please check your spelling!');
     }
 }