Add Dryrun mode for Rsync strategy

Update doc
This commit is contained in:
Jean-Noel Benoit 2015-10-28 18:45:12 +01:00
parent ac36fb29d5
commit 38467d9fc5
7 changed files with 172 additions and 32 deletions

View file

@ -129,6 +129,24 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
return self::$deployStatus;
}
/**
* Launch a Dry run command for Rsync strategy
* Without others sub tasks.
*/
public function dryRun()
{
if ($this->getConfig()->deployment('strategy') != 'rsync') {
Console::output('<red>Error : Dry-run task is only available when using Rsync strategy.</red>', 1, 1);
return 232;
}
else {
// Launch Pre-DryRun tasks.
$this->runNonDeploymentTasks(AbstractTask::STAGE_PRE_DRYRUN, $this->getConfig(), 'Pre-DryRun');
// Launch Deployment in dryrun mode (true).
$this->runDeploymentTasks(TRUE);
}
}
/**
* Deploys the Application
* @see \Mage\Command\AbstractCommand::run()
@ -153,6 +171,11 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
touch(getcwd() . '/.mage/~working.lock');
}
// If we are in dry run only
if ($this->getConfig()->getParameter('dry-run') === true) {
return $this->dryRun();
}
// Release ID
$this->getConfig()->setReleaseId(date('YmdHis'));
@ -229,7 +252,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
if (self::$deployStatus === self::FAILED) {
$exitCode = 1;
}
return $exitCode;
}
@ -306,7 +329,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
}
}
protected function runDeploymentTasks()
protected function runDeploymentTasks($dryrun = false)
{
if (self::$deployStatus == self::FAILED) {
return;
@ -340,7 +363,11 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
Console::output('Deploying to <bold>' . $this->getConfig()->getHost() . '</bold>');
$tasksToRun = $this->getConfig()->getTasks();
$tasksToRun = array();
if ($dryrun !== false) {
$tasksToRun = $this->getConfig()->getTasks();
}
$deployStrategy = $this->chooseDeployStrategy();
@ -382,7 +409,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
}
// Releasing
if (self::$deployStatus == self::SUCCEDED && $this->getConfig()->release('enabled', false) === true) {
if (self::$deployStatus == self::SUCCEDED && $dryrun !== true && $this->getConfig()->release('enabled', false) === true) {
// Execute the Releases
Console::output('Starting the <bold>Releasing</bold>');
$completedTasks = 0;
@ -522,7 +549,6 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment
if ($runTask === true) {
try {
$result = $task->run();
if ($result === true) {
Console::output('<green>OK</green>', 0);
$result = true;

View file

@ -28,6 +28,12 @@ abstract class AbstractTask
*/
const STAGE_PRE_DEPLOY = 'pre-deploy';
/**
* Stage Constant for Pre Dry-Run
* @var string
*/
const STAGE_PRE_DRYRUN = 'pre-dryrun';
/**
* Stage Constant for Deployment
* @var string

View file

@ -13,6 +13,7 @@ namespace Mage\Task\BuiltIn\Deployment\Strategy;
use Mage\Console;
use Mage\Task\BuiltIn\Deployment\Strategy\BaseStrategyTaskAbstract;
use Mage\Task\Releases\IsReleaseAware;
use Mage\Task\BuiltIn\Releases\ListTask;
/**
* Task for Sync the Local Code to the Remote Hosts via RSYNC
@ -27,6 +28,9 @@ class RsyncTask extends BaseStrategyTaskAbstract implements IsReleaseAware
*/
public function getName()
{
if ($this->getConfig()->getParameter('dry-run', false) === true) {
return 'Dry-run via Rsync [built-in]';
}
if ($this->getConfig()->release('enabled', false) === true) {
if ($this->getConfig()->getParameter('overrideRelease', false) === true) {
return 'Deploy via Rsync (with Releases override) [built-in]';
@ -43,27 +47,130 @@ class RsyncTask extends BaseStrategyTaskAbstract implements IsReleaseAware
}
}
/**
* @param bool|FALSE $dryRun
* @return string
*/
protected function getDeployCommand($dryRun = false)
{
$deployToDirectory = $this->getDeployToDirectory($dryRun);
$excludes = $this->getExcludes();
$excludesListFilePath = $this->getConfig()->deployment('excludes_file', '');
$strategyFlags = $this->getConfig()->deployment('strategy_flags', $this->getConfig()->general('strategy_flags', array()));
if (isset($strategyFlags['rsync'])) {
$strategyFlags = $strategyFlags['rsync'];
} else {
$strategyFlags = '';
}
// Add two flags if we are in Dry run.
if ($dryRun === true) {
$dryRunFlags = array(
'--dry-run',
'--itemize-changes',
'--omit-dir-times'
);
$strategyFlags = str_replace($dryRunFlags, '', $strategyFlags);
$strategyFlags .= implode(' ', $dryRunFlags);
}
$command = 'rsync -avz '
. $strategyFlags . ' '
. '--rsh="ssh ' . $this->getConfig()->getHostIdentityFileOption() . '-p' . $this->getConfig()->getHostPort() . '" '
. $this->excludes($excludes) . ' '
. $this->excludesListFile($excludesListFilePath) . ' '
. $this->getConfig()->deployment('from') . ' '
. ($this->getConfig()->deployment('user') ? $this->getConfig()->deployment('user') . '@' : '')
. $this->getConfig()->getHostName() . ':' . $deployToDirectory;
return $command;
}
/**
* @param bool|FALSE $dryRun
* @return string
*/
protected function getDeployToDirectory($dryRun = false)
{
$deployTo = rtrim($this->getConfig()->deployment('to'), '/');
// If releases aren't enabled, deploy dir is simply deploy to config.
if ($this->getConfig()->release('enabled', false) !== true) {
return $deployTo;
}
// If dryrun, check from the latest release.
if ($dryRun === true) {
$release = ListTask::getCurrentRelease();
}
else {
$release = $this->getConfig()->getReleaseId();
}
$releasesDirectory = $this->getConfig()->release('directory', 'releases');
$deployToDirectory = $deployTo . '/' . $releasesDirectory . '/' . $release;
return $deployToDirectory;
}
/**
* @return bool
*/
public function dryRun()
{
Console::output('');
if ($this->getConfig()->release('enabled', false) === true) {
$currentRelease = ListTask::getCurrentRelease();
Console::output('Checking files on the latest release <purple>'.$currentRelease.'</purple> on host <purple>'.$this->getConfig()->getHostName().'</purple>...', 2, 1);
}
else {
Console::output('Checking files on host <purple>'.$this->getConfig()->getHostName().'</purple>...', 2, 1);
}
// Get deploy command with dryRun option (true).
$command = $this->getDeployCommand(true);
$result = $this->runCommandLocal($command, $output);
// Put each line in an array (CHR(10) = Carriage return).
$lines = explode(CHR(10), $output);
if (count($lines)) {
Console::output('');
Console::output('<yellow>---------- Dry run result ------------</yellow>', 2, 1);
foreach ($lines as $key => $line) {
Console::output($line, 2, 1);
}
Console::output('<yellow>---------- End Dry run ---------------</yellow></yellow>', 2, 1);
}
return $result;
}
/**
* Syncs the Local Code to the Remote Host
* @see \Mage\Task\AbstractTask::run()
*/
public function run()
{
$excludes = $this->getExcludes();
// Launch dry run mode
if ($this->getConfig()->getParameter('dry-run') === true) {
return $this->dryRun();
}
$this->checkOverrideRelease();
$excludes = $this->getExcludes();
$excludesListFilePath = $this->getConfig()->deployment('excludes_file', '');
// If we are working with releases
$deployToDirectory = $this->getConfig()->deployment('to');
if ($this->getConfig()->release('enabled', false) === true) {
$releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->getConfig()->release('symlink', 'current');
$currentRelease = false;
$deployToDirectory = rtrim($this->getConfig()->deployment('to'), '/')
. '/' . $releasesDirectory
. '/' . $this->getConfig()->getReleaseId();
$deployToDirectory = $this->getDeployToDirectory();
Console::log('Deploy to ' . $deployToDirectory);
$resultFetch = $this->runCommandRemote('ls -ld ' . $symlink . ' | cut -d"/" -f2', $currentRelease);
@ -86,23 +193,7 @@ class RsyncTask extends BaseStrategyTaskAbstract implements IsReleaseAware
}
}
// Strategy Flags
$strategyFlags = $this->getConfig()->deployment('strategy_flags', $this->getConfig()->general('strategy_flags', array()));
if (isset($strategyFlags['rsync'])) {
$strategyFlags = $strategyFlags['rsync'];
} else {
$strategyFlags = '';
}
$command = 'rsync -avz '
. $strategyFlags . ' '
. '--rsh="ssh ' . $this->getConfig()->getHostIdentityFileOption() . '-p' . $this->getConfig()->getHostPort() . '" '
. $this->excludes($excludes) . ' '
. $this->excludesListFile($excludesListFilePath) . ' '
. $this->getConfig()->deployment('from') . ' '
. ($this->getConfig()->deployment('user') ? $this->getConfig()->deployment('user') . '@' : '')
. $this->getConfig()->getHostName() . ':' . $deployToDirectory;
$command = $this->getDeployCommand();
$result = $this->runCommandLocal($command);
return $result;

View file

@ -45,9 +45,7 @@ class ListTask extends AbstractTask implements IsReleaseAware
$releases = ($output == '') ? array() : explode(PHP_EOL, $output);
// Get Current
$result = $this->runCommandRemote('ls -l ' . $symlink, $output) && $result;
$currentRelease = explode('/', $output);
$currentRelease = trim(array_pop($currentRelease));
$currentRelease = $this->getCurrentRelease();
if (count($releases) == 0) {
Console::output('<bold>No releases available</bold> ... ', 2);
@ -92,6 +90,18 @@ class ListTask extends AbstractTask implements IsReleaseAware
}
}
/**
* Get the latest release.
*/
public function getCurrentRelease()
{
$symlink = $this->getConfig()->release('symlink', 'current');
$this->runCommandRemote('ls -l ' . $symlink, $output);
$currentRelease = explode('/', $output);
$currentRelease = trim(array_pop($currentRelease));
return $currentRelease;
}
/**
* Calculates a Human Readable Time Difference
* @param string $releaseDate

View file

@ -30,6 +30,9 @@ mage deploy to:production
# Deploys Application to Production environment, overriding the current release
mage deploy to:production --overrideRelease
# Don't deploy application, only output the files to be deployed (works with Rsync strategy only).
mage deploy to:production --dry-run
# Locks deployment to Production environment
mage lock to:production

View file

@ -14,6 +14,8 @@ hosts:
- s01.example.com
- s02.example.com
tasks:
pre-dryrun:
# - grunt
pre-deploy:
- scm/update
on-deploy:

View file

@ -14,6 +14,8 @@ hosts:
- localhost
- 127.0.0.1
tasks:
pre-dryrun:
# - grunt
pre-deploy:
# - sampleTask
# - failTask