Inheritance: extends DataObject
コード例 #1
0
 /**
  * Return data about a particular {@link Member} of the stack for use in API response.
  * Notes:
  * 1) This method returns null instead of an array if the member doesn't exists anymore
  * 2) 'role' can be null in the response. This is the case of an admin, or an operations
  * user who can create the deployment but is not part of the stack roles.
  *
  * @param \DNProject $project
  * @param int $memberID
  * @return null|array
  */
 public function getStackMemberData(\DNProject $project, $memberID)
 {
     if (empty(self::$_cache_project_members[$project->ID])) {
         self::$_cache_project_members[$project->ID] = $project->listMembers();
     }
     // we cache all member lookup, even the false results
     if (!isset(self::$_cache_members[$memberID])) {
         self::$_cache_members[$memberID] = \Member::get()->byId($memberID);
     }
     if (!self::$_cache_members[$memberID]) {
         return null;
     }
     $role = null;
     foreach (self::$_cache_project_members[$project->ID] as $stackMember) {
         if ($stackMember['MemberID'] !== $memberID) {
             continue;
         }
         $role = $stackMember['RoleTitle'];
     }
     // if an administator is approving, they should be shown as one
     if ($role === null && \Permission::checkMember(self::$_cache_members[$memberID], 'ADMIN')) {
         $role = 'Administrator';
     }
     return ['id' => $memberID, 'email' => self::$_cache_members[$memberID]->Email, 'role' => $role, 'name' => self::$_cache_members[$memberID]->getName()];
 }
コード例 #2
0
 public function testHasDiskQuota()
 {
     Config::inst()->update('DNProject', 'defaults', array('DiskQuotaMB' => 0));
     $this->assertFalse($this->project->HasDiskQuota());
     Config::inst()->update('DNProject', 'defaults', array('DiskQuotaMB' => 2048));
     $this->assertTrue($this->project->HasDiskQuota());
     $this->project->DiskQuotaMB = 2;
     $this->assertTrue($this->project->HasDiskQuota());
 }
 /**
  * Deploy the given build to the given environment.
  *
  * @param DNEnvironment $environment
  * @param DeploynautLogFile $log
  * @param DNProject $project
  * @param array $options
  */
 public function deploy(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project, $options)
 {
     $name = $environment->getFullName();
     $repository = $project->getLocalCVSPath();
     $sha = $options['sha'];
     $args = array('branch' => $sha, 'repository' => $repository);
     $this->extend('deployStart', $environment, $sha, $log, $project);
     $log->write(sprintf('Deploying "%s" to "%s"', $sha, $name));
     $this->enableMaintenance($environment, $log, $project);
     // Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
     // if build_filename isn't specified
     if ($this->packageGenerator) {
         $log->write(sprintf('Using package generator "%s"', get_class($this->packageGenerator)));
         try {
             $args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
         } catch (Exception $e) {
             $log->write($e->getMessage());
             throw $e;
         }
         if (empty($args['build_filename'])) {
             throw new RuntimeException('Failed to generate package.');
         }
     }
     $command = $this->getCommand('deploy', 'web', $environment, $args, $log);
     $command->run(function ($type, $buffer) use($log) {
         $log->write($buffer);
     });
     // Deployment cleanup. We assume it is always safe to run this at the end, regardless of the outcome.
     $self = $this;
     $cleanupFn = function () use($self, $environment, $args, $log) {
         $command = $self->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $this->extend('cleanupFailure', $environment, $sha, $log, $project);
             $log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
         }
     };
     // Once the deployment has run it's necessary to update the maintenance page status
     if (!empty($options['leaveMaintenancePage'])) {
         $this->enableMaintenance($environment, $log, $project);
     }
     if (!$command->isSuccessful()) {
         $cleanupFn();
         $this->extend('deployFailure', $environment, $sha, $log, $project);
         throw new RuntimeException($command->getErrorOutput());
     }
     // Check if maintenance page should be removed
     if (empty($options['leaveMaintenancePage'])) {
         $this->disableMaintenance($environment, $log, $project);
     }
     $cleanupFn();
     $log->write(sprintf('Deploy of "%s" to "%s" finished', $sha, $name));
     $this->extend('deployEnd', $environment, $sha, $log, $project);
 }
コード例 #4
0
 /**
  * Return a numerical counter for the given build.
  */
 protected static function buildname_to_counter($buildname, DNProject $project)
 {
     $builds = $project->DNBuildList()->reverse();
     $counter = 1;
     foreach ($builds as $build) {
         if ($build->FullName() == $buildname) {
             return $counter;
         }
         $counter++;
     }
 }
コード例 #5
0
ファイル: DNProject.php プロジェクト: adrexia/deploynaut
 /**
  * Used by the sync task
  *
  * @param string $path
  * @return \DNProject
  */
 public static function create_from_path($path)
 {
     $project = new DNProject();
     $project->Name = $path;
     $project->write();
     // add the administrators group as the viewers of the new project
     $adminGroup = Group::get()->filter('Code', 'administrators')->first();
     if ($adminGroup && $adminGroup->exists()) {
         $project->Viewers()->add($adminGroup);
     }
     return $project;
 }
コード例 #6
0
 /**
  * 
  */
 public function setUp()
 {
     $this->envPath = '/tmp/deploynaut_test/envs';
     Config::inst()->update('Injector', 'DNData', array('constructor' => array(0 => $this->envPath, 1 => '/tmp/deploynaut_test/gitkeys', 2 => Director::baseFolder() . '/assets/transfers')));
     parent::setUp();
     $this->project = new DNProject();
     $this->project->Name = 'testproject';
     $this->project->write();
     $this->env = new DNEnvironment();
     $this->env->Name = 'uat';
     $this->env->ProjectID = $this->project->ID;
     $this->env->write();
 }
コード例 #7
0
 /**
  * Construct fields to select any commit
  *
  * @param DNProject $project
  * @return FormField
  */
 protected function buildCommitSelector($project)
 {
     // Branches
     $branches = [];
     foreach ($project->DNBranchList() as $branch) {
         $sha = $branch->SHA();
         $name = $branch->Name();
         $branchValue = sprintf("%s (%s, %s old)", $name, substr($sha, 0, 8), $branch->LastUpdated()->TimeDiff());
         $branches[$sha . '-' . $name] = $branchValue;
     }
     // Tags
     $tags = [];
     foreach ($project->DNTagList()->setLimit(null) as $tag) {
         $sha = $tag->SHA();
         $name = $tag->Name();
         $tagValue = sprintf("%s (%s, %s old)", $name, substr($sha, 0, 8), $branch->LastUpdated()->TimeDiff());
         $tags[$sha . '-' . $name] = $tagValue;
     }
     $tags = array_reverse($tags);
     // Past deployments
     $redeploy = [];
     foreach ($project->DNEnvironmentList() as $dnEnvironment) {
         $envName = $dnEnvironment->Name;
         foreach ($dnEnvironment->DeployHistory()->filter('State', \DNDeployment::STATE_COMPLETED) as $deploy) {
             $sha = $deploy->SHA;
             if (!isset($redeploy[$envName])) {
                 $redeploy[$envName] = [];
             }
             if (!isset($redeploy[$envName][$sha])) {
                 $pastValue = sprintf("%s (deployed %s)", substr($sha, 0, 8), $deploy->obj('LastEdited')->Ago());
                 $redeploy[$envName][$sha] = $pastValue;
             }
         }
     }
     // Merge fields
     $releaseMethods = [];
     if (!empty($branches)) {
         $releaseMethods[] = new SelectionGroup_Item('Branch', new DropdownField('Branch', 'Select a branch', $branches), 'Deploy the latest version of a branch');
     }
     if ($tags) {
         $releaseMethods[] = new SelectionGroup_Item('Tag', new DropdownField('Tag', 'Select a tag', $tags), 'Deploy a tagged release');
     }
     if ($redeploy) {
         $releaseMethods[] = new SelectionGroup_Item('Redeploy', new GroupedDropdownField('Redeploy', 'Redeploy', $redeploy), 'Redeploy a release that was previously deployed (to any environment)');
     }
     $releaseMethods[] = new SelectionGroup_Item('SHA', new Textfield('SHA', 'Please specify the full SHA'), 'Deploy a specific SHA');
     $field = new TabbedSelectionGroup('SelectRelease', $releaseMethods);
     $field->setValue(reset($releaseMethods)->getValue());
     $field->addExtraClass('clearfix');
     return $field;
 }
 public function testURLParsing()
 {
     $shouldMatchURLs = array('https://github.com/silverstripe/deploynaut.git', 'github.com:silverstripe/deploynaut.git', 'git@github.com:silverstripe/deploynaut.git', 'ssh://git@github.com:22/silverstripe/deploynaut.git');
     $project = new DNProject();
     foreach ($shouldMatchURLs as $url) {
         $project->CVSPath = $url;
         $repositoryInterface = $project->getRepositoryInterface();
         $this->assertEquals('https://github.com/silverstripe/deploynaut', $repositoryInterface->URL, "Failed to extract repository from " . $url);
     }
     $shouldntMatchURLs = array('https://othersite.com/github.com/ranking');
     foreach ($shouldntMatchURLs as $url) {
         $project->CVSPath = $url;
         $repositoryInterface = $project->getRepositoryInterface();
         $this->assertNull($repositoryInterface);
     }
 }
コード例 #9
0
 /**
  * @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);
     }
 }
コード例 #10
0
ファイル: FetchJob.php プロジェクト: antons-/deploynaut
 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');
 }
コード例 #11
0
ファイル: DNProjectList.php プロジェクト: adrexia/deploynaut
 /**
  * Sync the in-db project list with a list of file paths
  * @param array $paths Array of pathnames
  * @param boolean $dryRun
  */
 public function syncWithPaths($paths, $dryRun = false)
 {
     foreach ($paths as $path) {
         if (!$this->filter('Name', $path)->count()) {
             $this->message($path);
             if (!$dryRun) {
                 DNProject::create_from_path($path)->write();
             }
         }
     }
 }
コード例 #12
0
 /**
  * @param string $environmentName
  * @return boolean True if this release has ever been deployed to the given environment
  */
 public function EverDeployedTo($environmentName)
 {
     $environments = $this->project->Environments()->filter('Name', $environmentName);
     if (!$environments->count()) {
         return false;
     }
     $environment = $environments->first();
     $deployments = DNDeployment::get()->filter('Status', 'Finished')->filter('EnvironmentID', $environment->ID);
     if ($deployments->count()) {
         return true;
     }
     return false;
 }
コード例 #13
0
 /**
  * @return array
  */
 protected function getReferences()
 {
     $branches = array();
     // Placeholder to put master branch first
     $firstBranch = null;
     try {
         $repository = new Gitonomy\Git\Repository($this->project->getLocalCVSPath());
     } catch (Exception $e) {
         return $branches;
     }
     foreach ($repository->getReferences()->getBranches() as $branch) {
         /** @var DNBranch $obj */
         $obj = DNBranch::create($branch, $this->project, $this->data);
         if ($branch->getName() == 'master') {
             $firstBranch = array($branch->getName() => $obj);
         } else {
             $branches[$branch->getName()] = $obj;
         }
     }
     if ($firstBranch) {
         $branches = $firstBranch + $branches;
     }
     return $branches;
 }
コード例 #14
0
ファイル: FetchJob.php プロジェクト: silverstripe/deploynaut
 /**
  * Run a shell command.
  *
  * @param string $command The command to run
  * @param string|null $workingDir The working dir to run command in
  * @throws RuntimeException
  */
 protected function runCommand($command, $workingDir = null)
 {
     if (!empty($this->user)) {
         $command = sprintf('sudo -u %s %s', $this->user, $command);
     }
     if ($this->log) {
         $this->log->write(sprintf('Running command: %s', $command));
     }
     $process = new AbortableProcess($command, $workingDir);
     $process->setEnv($this->project->getProcessEnv());
     $process->setTimeout(1800);
     $process->run();
     if (!$process->isSuccessful()) {
         throw new RuntimeException($process->getErrorOutput());
     }
 }
コード例 #15
0
 /**
  * @var array
  * @return \DeploymentStrategy
  */
 protected function createStrategy($options)
 {
     $strategy = $this->environment->Backend()->planDeploy($this->environment, $options);
     $data = $strategy->toArray();
     $interface = $this->project->getRepositoryInterface();
     if ($interface instanceof \ArrayData && $this->canCompareCodeVersions($interface, $data['changes'])) {
         $compareurl = sprintf('%s/compare/%s...%s', $interface->URL, $data['changes']['Code version']['from'], $data['changes']['Code version']['to']);
         $data['changes']['Code version']['compareUrl'] = $compareurl;
         // special case for .platform.yml field so we don't show a huge blob of changes,
         // but rather a link to where the .platform.yml changes were made in the code
         if (isset($data['changes']['.platform.yml other'])) {
             $data['changes']['.platform.yml other']['compareUrl'] = $compareurl;
             $data['changes']['.platform.yml other']['description'] = '';
         }
     }
     $this->extend('updateDeploySummary', $data);
     // Ensure changes that would have been updated are persisted in the object,
     // such as the comparison URL, so that they will be written to the Strategy
     // field on the DNDeployment object as part of {@link createDeployment()}
     $strategy->setChanges($data['changes']);
     return $strategy;
 }
コード例 #16
0
 /**
  * Find a build in this set by hash.
  *
  * @param string $hash
  * @return DNCommit
  */
 public function byName($hash)
 {
     if ($this->loaded === false) {
         $this->items = $this->getReferences();
         $this->loaded = true;
     }
     // The item might not be in the list because of the limit, try to find
     // in an older version and add it to the list.
     $found = null;
     foreach ($this->items as $item) {
         if ($item->SHA() == $hash) {
             $found = $item;
             break;
         }
     }
     if ($found === null) {
         $repository = new Gitonomy\Git\Repository($this->project->getLocalCVSPath());
         $commit = new Gitonomy\Git\Commit($repository, $hash);
         $found = DNCommit::create($commit, $this->project, $this->data);
     }
     return $found;
 }
コード例 #17
0
 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);
     }
 }
コード例 #18
0
ファイル: DNRoot.php プロジェクト: antons-/deploynaut
 /**
  * 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');
 }
コード例 #19
0
ファイル: DNRoot.php プロジェクト: silverstripe/deploynaut
 /**
  * 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;
 }
コード例 #20
0
ファイル: DeploynautAPI.php プロジェクト: antons-/deploynaut
 /**
  * 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();
 }
コード例 #21
0
 /**
  * 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();
 }
コード例 #22
0
 /**
  * @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;
 }
コード例 #23
0
ファイル: DNProject.php プロジェクト: antons-/deploynaut
 /**
  * Provides a list of environments found in this project.
  * CAUTION: filterByCallback will change this into an ArrayList!
  *
  * @return ArrayList
  */
 public function DNEnvironmentList()
 {
     if (!self::$_current_member_cache) {
         self::$_current_member_cache = Member::currentUser();
     }
     if (self::$_current_member_cache === false) {
         return new ArrayList();
     }
     $currentMember = self::$_current_member_cache;
     return $this->Environments()->filterByCallBack(function ($item) use($currentMember) {
         return $item->canView($currentMember);
     });
 }
コード例 #24
0
ファイル: DNData.php プロジェクト: ss23/deploynaut
 /**
  * Provide a list of all projects.
  * @return DataList
  */
 public function DNProjectList()
 {
     return DNProject::get();
 }
コード例 #25
0
ファイル: DNBranch.php プロジェクト: silverstripe/deploynaut
 public function Link()
 {
     // Use a get-var for branch so that it can handle unsafe chars better
     return Controller::join_links($this->project->Link(), 'branch?name=' . urlencode($this->Name()));
 }
コード例 #26
0
 /**
  * @return string
  */
 public function Link()
 {
     return \Controller::join_links($this->project->Link(), self::ACTION_GIT);
 }
コード例 #27
0
ファイル: Pipeline.php プロジェクト: hafriedlander/deploynaut
 /**
  * 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;
 }
コード例 #28
0
 /**
  * Validate a specific alert configuration from configuration YAML is correct.
  *
  * @param string $name
  * @param array $config
  * @param DNProject $project
  * @param DeploynautLogFile $log
  * @return boolean
  */
 public function validateAlert($name, $config, $project, $log)
 {
     // validate we have an environment set for the alert
     if (!isset($config['environment'])) {
         $log->write(sprintf('WARNING: Failed to configure alert "%s". Missing "environment" key in .alerts.yml. Skipped.', $name));
         return false;
     }
     // validate we have an environmentcheck suite name to check
     if (!isset($config['check_url'])) {
         $log->write(sprintf('WARNING: Failed to configure alert "%s". Missing "check_url" key in .alerts.yml. Skipped.', $name));
         return false;
     }
     // validate we have contacts for the alert
     if (!isset($config['contacts'])) {
         $log->write(sprintf('WARNING: Failed to configure alert "%s". Missing "contacts" key in .alerts.yml. Skipped.', $name));
         return false;
     }
     // validate that each value in the config is valid, build up a list of contacts we'll use later
     foreach ($config['contacts'] as $contactEmail) {
         // special case for ops
         if ($contactEmail == 'ops') {
             continue;
         }
         $contact = $project->AlertContacts()->filter('Email', $contactEmail)->first();
         if (!($contact && $contact->exists())) {
             $log->write(sprintf('WARNING: Failed to configure alert "%s". No such contact "%s". Skipped.', $name, $contactEmail));
             return false;
         }
     }
     // validate the environment specified in the alert actually exists
     if (!DNEnvironment::get()->filter('Name', $config['environment'])->first()) {
         $log->write(sprintf('WARNING: Failed to configure alert "%s". Invalid environment "%s" in .alerts.yml. Skipped.', $name, $config['environment']));
         return false;
     }
     return true;
 }
コード例 #29
0
ファイル: DNRoot.php プロジェクト: udomsak/deploynaut
 /**
  * Does the actual project creation.
  *
  * @param $data array
  * @param $form Form
  *
  * @return SS_HTTPResponse
  */
 public function doCreateProject($data, $form)
 {
     $form->loadDataFrom($data);
     $project = DNProject::create();
     $form->saveInto($project);
     $this->extend('onBeforeCreateProject', $project, $data, $form);
     try {
         if ($project->write() > 0) {
             $this->extend('onAfterCreateProject', $project, $data, $form);
             // If an extension hasn't redirected us, we'll redirect to the project.
             if (!$this->redirectedTo()) {
                 return $this->redirect($project->Link());
             } else {
                 return $this->response;
             }
         } else {
             $form->sessionMessage('Unable to write the stack to the database.', 'bad');
         }
     } catch (ValidationException $e) {
         $form->sessionMessage($e->getMessage(), 'bad');
     }
     return $this->redirectBack();
 }
コード例 #30
0
 /**
  * Deploy the given build to the given environment.
  *
  * @param \DNEnvironment $environment
  * @param \DeploynautLogFile $log
  * @param \DNProject $project
  * @param array $options
  */
 public function deploy(\DNEnvironment $environment, \DeploynautLogFile $log, \DNProject $project, $options)
 {
     $name = $environment->getFullName();
     $repository = $project->getLocalCVSPath();
     $sha = $options['sha'];
     $args = array('branch' => $sha, 'repository' => $repository);
     $this->extend('deployStart', $environment, $sha, $log, $project);
     $log->write(sprintf('Deploying "%s" to "%s"', $sha, $name));
     $this->enableMaintenance($environment, $log, $project);
     // Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
     // if build_filename isn't specified
     if ($this->packageGenerator) {
         $log->write(sprintf('Using package generator "%s"', get_class($this->packageGenerator)));
         try {
             $args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
         } catch (Exception $e) {
             $log->write($e->getMessage());
             throw $e;
         }
         if (empty($args['build_filename'])) {
             throw new RuntimeException('Failed to generate package.');
         }
     }
     $command = $this->getCommand('deploy', 'web', $environment, $args, $log);
     $command->run(function ($type, $buffer) use($log) {
         $log->write($buffer);
     });
     $error = null;
     $deploySuccessful = $command->isSuccessful();
     if ($deploySuccessful) {
         // Deployment automatically removes .htaccess, i.e. disables maintenance. Fine to smoketest.
         $deploySuccessful = $this->smokeTest($environment, $log);
     }
     if (!$deploySuccessful) {
         $this->enableMaintenance($environment, $log, $project);
         $rollbackSuccessful = $this->deployRollback($environment, $log, $project, $options, $args);
         if ($rollbackSuccessful) {
             // Again, .htaccess removed, maintenance off.
             $rollbackSuccessful = $this->smokeTest($environment, $log);
         }
         if (!$rollbackSuccessful) {
             $this->enableMaintenance($environment, $log, $project);
             $currentBuild = $environment->CurrentBuild();
             $this->extend('deployRollbackFailure', $environment, $currentBuild, $log, $project);
             $log->write('Rollback failed');
             $error = $command->getErrorOutput();
         } else {
             $error = 'Rollback successful';
         }
     }
     // Regardless of outcome, try to clean up.
     $cleanup = $this->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
     $cleanup->run(function ($type, $buffer) use($log) {
         $log->write($buffer);
     });
     if (!$cleanup->isSuccessful()) {
         $this->extend('cleanupFailure', $environment, $sha, $log, $project);
         $log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
     }
     $this->extend('deployEnd', $environment, $sha, $log, $project);
     if ($error !== null) {
         throw new RuntimeException($error);
     }
     $log->write(sprintf('Deploy of "%s" to "%s" finished', $sha, $name));
 }