Exemple #1
0
 public function perform()
 {
     set_time_limit(0);
     $log = new DeploynautLogFile($this->args['logfile']);
     $projects = DNProject::get()->filter('Name', Convert::raw2sql($this->args['projectName']));
     $project = $projects->first();
     $path = $project->getLocalCVSPath();
     $env = $this->args['env'];
     $log->write('Starting git fetch for project "' . $project->Name . '"');
     // if an alternate user has been configured for clone, run the command as that user
     // @todo Gitonomy doesn't seem to have any way to prefix the command properly, if you
     // set 'sudo -u composer git' as the "command" parameter, it tries to run the whole
     // thing as a single command and fails
     $user = DNData::inst()->getGitUser();
     if (!empty($user)) {
         $command = sprintf('cd %s && sudo -u %s git fetch -p origin +refs/heads/*:refs/heads/* --tags', $path, $user);
         $process = new \Symfony\Component\Process\Process($command);
         $process->setEnv($env);
         $process->setTimeout(3600);
         $process->run();
         if (!$process->isSuccessful()) {
             throw new RuntimeException($process->getErrorOutput());
         }
     } else {
         $repository = new Gitonomy\Git\Repository($path, array('environment_variables' => $env));
         $repository->run('fetch', array('-p', 'origin', '+refs/heads/*:refs/heads/*', '--tags'));
     }
     $log->write('Git fetch is finished');
 }
 /**
  * @param SS_HTTPRequest $request
  */
 public function run($request = null)
 {
     $projects = DNProject::get();
     foreach ($projects as $project) {
         $environments = $project->DNEnvironmentList();
         foreach ($environments as $environment) {
             $newFilename = basename($environment->Filename);
             if ($environment->Filename != $newFilename) {
                 echo 'Migrating "' . $environment->Filename . '" to ' . $newFilename . PHP_EOL;
                 $environment->Filename = $newFilename;
                 $environment->write();
             }
         }
     }
     $warnings = false;
     // Check if all project folders exists
     foreach ($projects as $project) {
         if (!$project->projectFolderExists()) {
             $warnings = true;
             echo 'Project ' . $project->Name . ' don\'t have a cap project folder' . PHP_EOL;
         }
     }
     if ($warnings) {
         exit(1);
     }
 }
Exemple #3
0
 public function perform()
 {
     set_time_limit(0);
     if (!empty($this->args['logfile'])) {
         $this->log = new DeploynautLogFile($this->args['logfile']);
     }
     $this->project = DNProject::get()->byId($this->args['projectID']);
     if (!($this->project && $this->project->exists())) {
         throw new RuntimeException(sprintf('Project ID %s not found', $this->args['projectID']));
     }
     $this->user = DNData::inst()->getGitUser() ?: null;
     // Disallow concurrent git fetches on the same project.
     // Only consider fetches started in the last 30 minutes (older jobs probably got stuck)
     try {
         if (!empty($this->args['fetchID'])) {
             $runningFetches = DNGitFetch::get()->filter(array('ProjectID' => $this->project->ID, 'Status' => array('Queued', 'Started'), 'Created:GreaterThan' => strtotime('-30 minutes')))->exclude('ID', $this->args['fetchID']);
             if ($runningFetches->count()) {
                 $runningFetch = $runningFetches->first();
                 $message = sprintf('Another fetch is in progress (started at %s by %s)', $runningFetch->dbObject('Created')->Nice(), $runningFetch->Deployer()->Title);
                 if ($this->log) {
                     $this->log->write($message);
                 }
                 throw new RuntimeException($message);
             }
         }
         // Decide whether we need to just update what we already have
         // or initiate a clone if no local repo exists.
         if ($this->project->repoExists() && empty($this->args['forceClone'])) {
             $this->fetchRepo();
         } else {
             $this->cloneRepo();
         }
     } catch (Exception $e) {
         if ($this->log) {
             $this->log->write($e->getMessage());
         }
         throw $e;
     }
     $this->project->clearGitCache();
     $this->updateStatus('Finished');
 }
 public function run($request = null)
 {
     // should syncing remove obsolete records?
     $remove = true;
     $dryRun = true;
     if ($request && $request->requestVar('remove') !== NULL) {
         $remove = (bool) $request->requestVar('remove');
     }
     if ($request && $request->requestVar('dryrun') !== NULL) {
         $dryRun = (bool) $request->requestVar('dryrun');
     }
     if ($dryRun) {
         echo "Running in dry run mode, no changes commited, ";
         echo "the output shows a prediction on what will happen." . PHP_EOL;
         echo "To skip dryrun, run the task like this:" . PHP_EOL;
         echo "./framework/sake dev/tasks/SyncProjectsAndEnvironments dryrun=0" . PHP_EOL . PHP_EOL;
         sleep(3);
     }
     $data = Injector::inst()->get('DNData');
     $projectPaths = $data->getProjectPaths();
     // Sync projects
     $projects = DNProject::get();
     if ($remove) {
         $this->echoHeader('Removing obsolete projects');
         $projects->removeObsolete($projectPaths, $dryRun);
     }
     $this->echoHeader('Adding new projects');
     $projects->syncWithPaths($projectPaths, $dryRun);
     $this->echoHeader('Syncing environment files');
     foreach ($projects as $project) {
         $this->echoHeader($project->Name);
         // Sync environments for each project
         $environmentPaths = $data->getEnvironmentPaths($project->Name);
         $project->DNEnvironmentList()->removeObsolete($environmentPaths, $dryRun);
         $project->DNEnvironmentList()->syncWithPaths($environmentPaths, $dryRun);
     }
 }
Exemple #5
0
 /**
  * Provide a list of all projects.
  *
  * @return SS_List
  */
 public function DNProjectList()
 {
     $memberId = Member::currentUserID();
     if (!$memberId) {
         return new ArrayList();
     }
     if (Permission::check('ADMIN')) {
         return DNProject::get();
     }
     $projects = Member::get()->filter('ID', $memberId)->relation('Groups')->relation('Projects');
     $this->extend('updateDNProjectList', $projects);
     return $projects;
 }
Exemple #6
0
 /**
  * Get environment from URL
  *
  * @return DNEnvironment
  */
 protected function getEnvironment()
 {
     $projectName = $this->getRequest()->param('Project');
     $project = DNProject::get()->filter('Name', $projectName)->first();
     $environmentName = $this->getRequest()->param('Environment');
     return $project->Environments()->filter('Name', $environmentName)->first();
 }
 /**
  * Extracts a *.sspak file referenced through the passed in $dataTransfer
  * and pushes it to the environment referenced in $dataTransfer.
  *
  * @param  DNDataTransfer    $dataTransfer
  * @param  DeploynautLogFile $log
  */
 protected function dataTransferRestore(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
 {
     $environmentObj = $dataTransfer->Environment();
     $project = $environmentObj->Project();
     $projectName = $project->Name;
     $environmentName = $environmentObj->Name;
     $env = $project->getProcessEnv();
     $project = DNProject::get()->filter('Name', $projectName)->first();
     $name = $projectName . ':' . $environmentName;
     $tempPath = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
     mkdir($tempPath, 0700, true);
     $self = $this;
     $cleanupFn = function () use($self, $tempPath, $name, $env, $log) {
         // Rebuild even if failed - maybe we can at least partly recover.
         $self->rebuild($name, $env, $log);
         $process = new Process('rm -rf ' . escapeshellarg($tempPath));
         $process->run();
     };
     // Extract *.sspak to a temporary location
     $log->write('Extracting *.sspak file');
     $sspakFilename = $dataTransfer->DataArchive()->ArchiveFile()->FullPath;
     $sspakCmd = sprintf('sspak extract %s %s', escapeshellarg($sspakFilename), escapeshellarg($tempPath));
     $log->write($sspakCmd);
     $process = new Process($sspakCmd);
     $process->setTimeout(3600);
     $process->run();
     if (!$process->isSuccessful()) {
         $log->write('Could not extract the *.sspak file: ' . $process->getErrorOutput());
         $cleanupFn();
         throw new RuntimeException($process->getErrorOutput());
     }
     // TODO Validate that file actually contains the desired modes
     // Restore database
     if (in_array($dataTransfer->Mode, array('all', 'db'))) {
         // Upload into target environment
         $log->write('Restore of database to "' . $name . '" started');
         $args = array('data_path' => $tempPath . DIRECTORY_SEPARATOR . 'database.sql.gz');
         $command = $this->getCommand('data:pushdb', 'db', $name, $args, $env, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write('Restore of database to "' . $name . '" failed: ' . $command->getErrorOutput());
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write('Restore of database to "' . $name . '" done');
     }
     // Restore assets
     if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
         // Upload into target environment
         $log->write('Restore of assets to "' . $name . '" started');
         // Extract assets.tar.gz into assets/
         $extractCmd = sprintf('cd %s && tar xzf %s', escapeshellarg($tempPath), escapeshellarg($tempPath . DIRECTORY_SEPARATOR . 'assets.tar.gz'));
         $log->write($extractCmd);
         $process = new Process($extractCmd);
         $process->setTimeout(3600);
         $process->run();
         if (!$process->isSuccessful()) {
             $log->write('Could not extract the assets archive');
             $cleanupFn();
             throw new RuntimeException($process->getErrorOutput());
         }
         $args = array('data_path' => $tempPath . DIRECTORY_SEPARATOR . 'assets');
         $command = $this->getCommand('data:pushassets', 'web', $name, $args, $env, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write('Restore of assets to "' . $name . '" failed: ' . $command->getErrorOutput());
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write('Restore of assets to "' . $name . '" done');
     }
     $log->write('Rebuilding and cleaning up');
     $cleanupFn();
 }
Exemple #8
0
 /**
  * Provide a list of all projects.
  * @return DataList
  */
 public function DNProjectList()
 {
     return DNProject::get();
 }
 /**
  * @return ValidationResult
  */
 protected function validate()
 {
     $validation = parent::validate();
     if ($validation->valid()) {
         if (empty($this->Name)) {
             return $validation->error('The stack must have a name.');
         }
         // The name is used to build filepaths so should be restricted
         if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\\-\\_]+$/', $this->Name)) {
             return $validation->error('Project name can only contain alphanumeric, hyphens and underscores.');
         }
         if (empty($this->CVSPath)) {
             return $validation->error('You must provide a repository URL.');
         }
         $existing = DNProject::get()->filter('Name', $this->Name);
         if ($this->ID) {
             $existing = $existing->exclude('ID', $this->ID);
         }
         if ($existing->count() > 0) {
             return $validation->error('A stack already exists with that name.');
         }
     }
     return $validation;
 }
 /**
  * Sync the in-db project list with a list of file paths
  * @param array $paths Array of pathnames
  * @param boolean $dryRun
  */
 public function syncProjectPaths($paths, $dryRun = false)
 {
     foreach ($paths as $path) {
         if (!DNProject::get()->filter('Name', $path)->count()) {
             $this->message($path);
             if (!$dryRun) {
                 DNProject::create_from_path($path)->write();
             }
         }
     }
 }
Exemple #11
0
 /**
  * Return a dependent {@link DNEnvironment} based on this pipeline's dependent environment configuration.
  * @return DNEnvironment
  */
 public function getDependentEnvironment()
 {
     // dependent environment not available
     $projectName = $this->getConfigSetting('PipelineConfig', 'DependsOnProject');
     $environmentName = $this->getConfigSetting('PipelineConfig', 'DependsOnEnvironment');
     if (empty($projectName) || empty($environmentName)) {
         return null;
     }
     $project = DNProject::get()->filter('Name', $projectName)->first();
     if (!($project && $project->exists())) {
         throw new Exception(sprintf('Could not find dependent project "%s"', $projectName));
     }
     $environment = DNEnvironment::get()->filter(array('ProjectID' => $project->ID, 'Name' => $environmentName))->first();
     if (!($environment && $environment->exists())) {
         throw new Exception(sprintf('Could not find dependent environment "%s" in project "%s"', $environmentName, $projectName));
     }
     return $environment;
 }
Exemple #12
0
 /**
  * Provide a list of all projects.
  *
  * @return SS_List
  */
 public function DNProjectList()
 {
     $memberId = Member::currentUserID();
     if (!$memberId) {
         return new ArrayList();
     }
     if (Permission::check('ADMIN')) {
         return DNProject::get();
     }
     return Member::get()->filter('ID', $memberId)->relation('Groups')->relation('Projects');
 }
Exemple #13
0
 /**
  * Provide a list of all projects.
  * CAUTION: filterByCallback will change this into an ArrayList!
  *
  * @return ArrayList
  */
 public function DNProjectList()
 {
     return DNProject::get()->filterByCallback(function ($record) {
         return $record->canView();
     });
 }