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); } }
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); } }
/** * 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; }
/** * 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(); }
/** * 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(); } } } }
/** * 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; }
/** * 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'); }
/** * 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(); }); }