コード例 #1
0
 /**
  * Links the release being deployed.
  *
  * @param DeployReleaseEvent       $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  */
 public function onDeployOrRollbackReleaseLinkRelease(DeployReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $release = $event->getRelease();
     $host = $release->getWorkspace()->getHost();
     $connection = $this->ensureConnection($host);
     $releasePath = $host->getPath() . '/' . $host->getStage();
     $context = array('linkTarget' => $releasePath, 'releaseVersion' => $release->getVersion(), 'event.task.action' => TaskInterface::ACTION_IN_PROGRESS);
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Linking "{linkTarget}" to release "{releaseVersion}".', $eventName, $this, $context));
     if ($connection->isLink($releasePath) === false || $connection->readLink($releasePath) !== $release->getPath()) {
         if ($connection->isLink($releasePath)) {
             $connection->delete($releasePath, false);
         }
         if ($connection->link($release->getPath(), $releasePath)) {
             $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
             $context['output.resetLine'] = true;
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Linked "{linkTarget}" to release "{releaseVersion}".', $eventName, $this, $context));
         } else {
             $context['event.task.action'] = TaskInterface::ACTION_FAILED;
             $context['output.resetLine'] = true;
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Linking "{linkTarget}" to release "{releaseVersion}" failed.', $eventName, $this, $context));
             throw new TaskRuntimeException(sprintf('Linking "%s" to release "%s" failed.', $context['linkTarget'], $context['releaseVersion']), $this);
         }
     } else {
         $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
         $context['output.resetLine'] = true;
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Link "{linkTarget}" to release "{releaseVersion}" already exists.', $eventName, $this, $context));
     }
 }
コード例 #2
0
 /**
  * Executes the configured command.
  *
  * @param Event                    $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  *
  * @throws TaskRuntimeException when execution of the command has failed.
  */
 public function onEvent(Event $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     if (in_array($eventName, $this->events)) {
         if ($event instanceof ReleaseEvent) {
             $release = $event->getRelease();
             $host = $release->getWorkspace()->getHost();
             $path = $release->getPath();
         } else {
             $host = $event->getWorkspace()->getHost();
             $path = $host->getPath();
         }
         $connection = $this->ensureConnection($host);
         $currentWorkingDirectory = $connection->getWorkingDirectory();
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Executing command "{command}".', $eventName, $this, array('command' => $this->command, 'event.task.action' => TaskInterface::ACTION_IN_PROGRESS)));
         $connection->changeWorkingDirectory($path);
         $result = $connection->executeCommand($this->command, $this->arguments);
         $connection->changeWorkingDirectory($currentWorkingDirectory);
         if ($result->isSuccessful()) {
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Executed command "{command}".', $eventName, $this, array('command' => $this->command, 'event.task.action' => TaskInterface::ACTION_COMPLETED, 'output.resetLine' => true)));
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::DEBUG, "{separator} Command output:{separator}\n{command.result}{separator}", $eventName, $this, array('command.result' => $result->getOutput(), 'separator' => "\n=================\n")));
         } else {
             throw new TaskCommandExecutionException(sprintf('Failed executing command "%s".', $this->command), $result, $this);
         }
     }
 }
コード例 #3
0
 /**
  * Creates a checkout of the repository for the release.
  *
  * @param PrepareReleaseEvent      $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  *
  * @throws TaskRuntimeException when the checkout of the repository has failed.
  */
 public function onPrepareReleaseCheckoutRepository(PrepareReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $context = array('repositoryUrl' => $this->repositoryUrl, 'version' => $event->getRelease()->getVersion(), 'event.task.action' => TaskInterface::ACTION_IN_PROGRESS);
     $connection = $this->ensureConnection($event->getRelease()->getWorkspace()->getHost());
     $processExecutor = new ConnectionAdapterProcessExecutor($connection);
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Creating checkout of repository "{repositoryUrl}" for version "{version}".', $eventName, $this, $context));
     $repository = new Repository($this->repositoryUrl, $event->getRelease()->getPath(), $processExecutor);
     if ($repository->checkout($event->getRelease()->getVersion())) {
         $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
         $context['output.resetLine'] = true;
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Created checkout of repository "{repositoryUrl}" for version "{version}".', $eventName, $this, $context));
     } else {
         throw new TaskCommandExecutionException(sprintf('Failed to checkout version "%s" from repository "%s".', $event->getRelease()->getVersion(), $this->repositoryUrl), $processExecutor->getLastProcessExecutionResult(), $this);
     }
 }
コード例 #4
0
 /**
  * Sets the correct permissions and group for the configured path.
  *
  * @param InstallReleaseEvent      $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  *
  * @throws TaskRuntimeException
  */
 public function onInstallReleaseUpdateFilePermissions(InstallReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $host = $event->getRelease()->getWorkspace()->getHost();
     $connection = $this->ensureConnection($host);
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Updating permissions for the configured paths...', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_IN_PROGRESS)));
     $releasePath = $event->getRelease()->getPath();
     $result = true;
     foreach ($this->paths as $path => $pathSettings) {
         $result = $result && $this->updateFilePermissions($connection, $releasePath, $path, $pathSettings);
     }
     if ($result === true) {
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Updated permissions for the configured paths.', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_COMPLETED, 'output.resetLine' => true)));
     } else {
         throw new TaskRuntimeException('Failed updating the permissions for the configured paths.', $this);
     }
 }
コード例 #5
0
 /**
  * Saves a YAML configuration file to a path within the release.
  *
  * @param InstallReleaseEvent      $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  */
 public function onInstallReleaseCreateOrUpdateConfiguration(InstallReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $release = $event->getRelease();
     $this->gatherEnvironmentVariables($release);
     $connection = $this->ensureConnection($release->getWorkspace()->getHost());
     $configurationFile = $release->getPath() . $this->configurationFile;
     $configurationDistributionFile = $configurationFile . '.dist';
     $context = array('action' => 'Creating', 'configurationFile' => $configurationFile, 'event.task.action' => TaskInterface::ACTION_IN_PROGRESS);
     if ($connection->isFile($configurationFile)) {
         $context['action'] = 'Updating';
     }
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, '{action} configuration file "{configurationFile}"...', $eventName, $this, $context));
     $yamlConfiguration = $this->getYamlConfiguration($connection, $release->getWorkspace()->getHost()->getStage(), $configurationFile, $configurationDistributionFile);
     if ($connection->putContents($configurationFile, $yamlConfiguration)) {
         $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
         if ($context['action'] === 'Creating') {
             $context['action'] = 'Created';
         } else {
             $context['action'] = 'Updated';
         }
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, '{action} configuration file "{configurationFile}".', $eventName, $this, $context));
     } else {
         $context['event.task.action'] = TaskInterface::ACTION_FAILED;
         $context['action'] = strtolower($context['action']);
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::WARNING, 'Failed {action} configuration file "{configurationFile}".', $eventName, $this, $context));
     }
 }
コード例 #6
0
 /**
  * {@inheritdoc}
  */
 public function deploy($version, $stage)
 {
     $successfulDeploy = true;
     $hosts = $this->configuration->getHostsByStage($stage);
     foreach ($hosts as $host) {
         $exception = null;
         $deployEventName = AccompliEvents::DEPLOY_RELEASE;
         $deployCompleteEventName = AccompliEvents::DEPLOY_RELEASE_COMPLETE;
         $deployFailedEventName = AccompliEvents::DEPLOY_RELEASE_FAILED;
         $title = new Title($this->logger->getOutput(), sprintf('Deploying release "%s" to "%s":', $version, $host->getHostname()));
         $title->render();
         try {
             $this->eventDispatcher->dispatch(AccompliEvents::CREATE_CONNECTION, new HostEvent($host));
             $workspaceEvent = new WorkspaceEvent($host);
             $this->eventDispatcher->dispatch(AccompliEvents::GET_WORKSPACE, $workspaceEvent);
             $workspace = $workspaceEvent->getWorkspace();
             if ($workspace instanceof Workspace) {
                 $prepareDeployReleaseEvent = new PrepareDeployReleaseEvent($workspace, $version);
                 $this->eventDispatcher->dispatch(AccompliEvents::PREPARE_DEPLOY_RELEASE, $prepareDeployReleaseEvent);
                 $release = $prepareDeployReleaseEvent->getRelease();
                 if ($release instanceof Release) {
                     $currentRelease = $prepareDeployReleaseEvent->getCurrentRelease();
                     if ($currentRelease instanceof Release && Comparator::lessThan($release->getVersion(), $currentRelease->getVersion())) {
                         $deployEventName = AccompliEvents::ROLLBACK_RELEASE;
                         $deployCompleteEventName = AccompliEvents::ROLLBACK_RELEASE_COMPLETE;
                         $deployFailedEventName = AccompliEvents::ROLLBACK_RELEASE_FAILED;
                     }
                     $deployReleaseEvent = new DeployReleaseEvent($release, $currentRelease);
                     $this->eventDispatcher->dispatch($deployEventName, $deployReleaseEvent);
                     $this->eventDispatcher->dispatch($deployCompleteEventName, $deployReleaseEvent);
                     continue;
                 }
                 throw new RuntimeException(sprintf('No task configured to initialize release version "%s" for deployment.', $version));
             }
             throw new RuntimeException('No task configured to initialize the workspace.');
         } catch (Exception $exception) {
         }
         $successfulDeploy = false;
         $failedEvent = new FailedEvent($this->eventDispatcher->getLastDispatchedEventName(), $this->eventDispatcher->getLastDispatchedEvent(), $exception);
         $this->eventDispatcher->dispatch($deployFailedEventName, $failedEvent);
     }
     return $successfulDeploy;
 }
コード例 #7
0
 /**
  * Creates the workspace directories when not already existing.
  *
  * @param WorkspaceEvent           $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  *
  * @throws TaskRuntimeException when the workspace path doesn't exist and can't be created.
  */
 public function onPrepareWorkspaceCreateWorkspace(WorkspaceEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $workspace = $event->getWorkspace();
     $connection = $this->ensureConnection($workspace->getHost());
     $workspacePath = $workspace->getHost()->getPath();
     if ($connection->isDirectory($workspacePath) === false && $connection->createDirectory($workspacePath) === false) {
         throw new TaskRuntimeException(sprintf('The workspace path "%s" does not exist and could not be created.', $workspacePath), $this);
     }
     $directories = array_merge(array($workspace->getReleasesDirectory(), $workspace->getDataDirectory(), $workspace->getCacheDirectory()), $workspace->getOtherDirectories());
     foreach ($directories as $directory) {
         $context = array('directory' => $directory, 'event.task.action' => TaskInterface::ACTION_IN_PROGRESS);
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Creating directory "{directory}".', $eventName, $this, $context));
         if ($connection->isDirectory($directory) === false) {
             if ($connection->createDirectory($directory)) {
                 $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
                 $context['output.resetLine'] = true;
                 $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Created directory "{directory}".', $eventName, $this, $context));
             } else {
                 $context['event.task.action'] = TaskInterface::ACTION_FAILED;
                 $context['output.resetLine'] = true;
                 $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::WARNING, 'Failed creating directory "{directory}".', $eventName, $this, $context));
             }
         } else {
             $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
             $context['output.resetLine'] = true;
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Directory "{directory}" exists.', $eventName, $this, $context));
         }
     }
 }
コード例 #8
0
 /**
  * Links the maintenance page to the stage being deployed.
  *
  * @param PrepareDeployReleaseEvent $event
  * @param string                    $eventName
  * @param EventDispatcherInterface  $eventDispatcher
  *
  * @throws TaskRuntimeException when not able to link the maintenance page.
  */
 public function onPrepareDeployReleaseLinkMaintenancePageToStage(PrepareDeployReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     if (VersionCategoryComparator::matchesStrategy($this->strategy, $event->getRelease(), $event->getCurrentRelease()) === false) {
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Skipped linking maintenance page according to strategy.', $eventName, $this));
         return;
     }
     $host = $event->getWorkspace()->getHost();
     $connection = $this->ensureConnection($host);
     $linkSource = $host->getPath() . '/maintenance/';
     $linkTarget = $host->getPath() . '/' . $host->getStage();
     $context = array('linkTarget' => $linkTarget);
     if ($connection->isLink($linkTarget) && $connection->delete($linkTarget, false) === false) {
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::WARNING, 'Failed to remove existing "{linkTarget}" link.', $eventName, $this, $context));
     }
     $context['event.task.action'] = TaskInterface::ACTION_IN_PROGRESS;
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Linking "{linkTarget}" to maintenance page.', $eventName, $this, $context));
     if ($connection->link($linkSource, $linkTarget)) {
         $context['event.task.action'] = TaskInterface::ACTION_COMPLETED;
         $context['output.resetLine'] = true;
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Linked "{linkTarget}" to maintenance page.', $eventName, $this, $context));
     } else {
         $context['event.task.action'] = TaskInterface::ACTION_FAILED;
         $context['output.resetLine'] = true;
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Linking "{linkTarget}" to maintenance page failed.', $eventName, $this, $context));
         throw new TaskRuntimeException(sprintf('Linking "%s" to maintenance page failed.', $context['linkTarget']), $this);
     }
 }
コード例 #9
0
 /**
  * Adds an SSH key to the initialized SSH agent.
  *
  * @param Workspace                  $workspace
  * @param ConnectionAdapterInterface $connection
  * @param string                     $key
  * @param string                     $eventName
  * @param EventDispatcherInterface   $eventDispatcher
  */
 private function addKeyToSSHAgent(Workspace $workspace, ConnectionAdapterInterface $connection, $key, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Adding key to SSH agent...', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_IN_PROGRESS)));
     $keyFile = $workspace->getHost()->getPath() . '/tmp.key';
     if ($connection->createFile($keyFile, 0700) && $connection->putContents($keyFile, $key)) {
         $result = $connection->executeCommand('ssh-add', array($keyFile));
         if ($result->isSuccessful()) {
             $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Added key to SSH agent.', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_COMPLETED, 'output.resetLine' => true)));
         }
         $connection->delete($keyFile);
         if ($result->isSuccessful()) {
             return;
         }
     }
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::INFO, 'Failed adding key to SSH agent.', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_FAILED, 'output.resetLine' => true)));
 }
コード例 #10
0
 /**
  * Runs the Composer install command to install the dependencies for the release.
  *
  * @param InstallReleaseEvent      $event
  * @param string                   $eventName
  * @param EventDispatcherInterface $eventDispatcher
  *
  * @throws TaskRuntimeException
  */
 public function onInstallReleaseExecuteComposerInstall(InstallReleaseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     $release = $event->getRelease();
     $host = $release->getWorkspace()->getHost();
     $connection = $this->ensureConnection($host);
     $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Installing Composer dependencies.', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_IN_PROGRESS)));
     $authenticationFile = $release->getPath() . '/auth.json';
     if (empty($this->authentication) === false) {
         $connection->putContents($authenticationFile, json_encode($this->authentication));
     }
     $connection->changeWorkingDirectory($host->getPath());
     $result = $connection->executeCommand(sprintf('php composer.phar install --no-interaction --working-dir="%s" --no-dev --no-scripts --optimize-autoloader', $release->getPath()));
     if ($connection->isFile($authenticationFile)) {
         $connection->delete($authenticationFile);
     }
     if ($result->isSuccessful()) {
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::NOTICE, 'Installed Composer dependencies.', $eventName, $this, array('event.task.action' => TaskInterface::ACTION_COMPLETED, 'output.resetLine' => true)));
         $eventDispatcher->dispatch(AccompliEvents::LOG, new LogEvent(LogLevel::DEBUG, "{separator} Command output:{separator}\n{command.result}{separator}", $eventName, $this, array('command.result' => $result->getOutput(), 'separator' => "\n=================\n")));
     } else {
         throw new TaskCommandExecutionException('Failed installing Composer dependencies.', $result, $this);
     }
 }