Skip to content

Commit

Permalink
Merge pull request #123 from fortrabbit/fix/import-errors
Browse files Browse the repository at this point in the history
Better error handling for copy/db/up --force
  • Loading branch information
Oliver Stark authored Sep 24, 2021
2 parents f2987cd + f486776 commit 3735d24
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 39 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 1.0.6 - 2021-09-24
- Exclude `resourcepaths` table from db backup
- Ignore mysql import errors 🤞🏻
- Better error output

## 1.0.5 - 2021-05-12
- Update craft-auto-migrate to use `project-config/apply`
- Code style cleanup
Expand Down
32 changes: 25 additions & 7 deletions bin/craft-copy-import-db.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,43 @@
exit(1);
}

$credentialsFile = "/tmp/mysql-extra.cnf";
$credentialsFileContent = [
"[client]",
"user=" . getenv('DB_USER'),
"password=" . getenv('DB_PASSWORD'),
"host=" . getenv('DB_SERVER')
];

if (false === file_put_contents($credentialsFile, join(PHP_EOL, $credentialsFileContent))) {
echo "ERROR: unable to write $credentialsFile";
exit(1);
}

$cmd = 'mysql -u {DB_USER} -p{DB_PASSWORD} -h {DB_SERVER} {DB_DATABASE} < {file} && echo 1';
$tokens = [
'{file}' => $file,
'{DB_USER}' => getenv('DB_USER'),
'{DB_PASSWORD}' => getenv('DB_PASSWORD'),
'{DB_SERVER}' => getenv('DB_SERVER'),
'{FILE}' => $file,
'{EXTRA_FILE}' => $credentialsFile,
'{DB_DATABASE}' => getenv('DB_DATABASE'),
];

$cmd = 'mysql --defaults-extra-file={EXTRA_FILE} --force {DB_DATABASE} < {FILE} && echo 1';
$cmd = str_replace(array_keys($tokens), array_values($tokens), $cmd);

$process = \Symfony\Component\Process\Process::fromShellCommandline($cmd);
$process->run();

unlink($credentialsFile);

if ($stderr = $process->getErrorOutput()) {
fwrite(STDERR, 'ERROR (sql):' . PHP_EOL);
fwrite(STDERR, substr($stderr, 0, 200));
exit(1);
}

if ($process->isSuccessful()) {
echo 'OK';
exit(0);
}

echo "ERROR: ";
echo $process->getErrorOutput();
fwrite(STDERR, 'ERROR (unknown)');
exit(1);
58 changes: 36 additions & 22 deletions src/Actions/DbUpAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public function run(?string $stage = null)
return ExitCode::UNSPECIFIED_ERROR;
}

if ($plugin->ssh->exec('ls vendor/bin/craft-copy-import-db.php | wc -l')) {
if (trim($plugin->ssh->getOutput()) !== '1') {
return $this->printAndExit(new PluginNotInstalledException());
}
}

$bar = $this->createProgressBar($steps);

// Step 1: Create dump of the current database
Expand Down Expand Up @@ -83,13 +89,7 @@ public function run(?string $stage = null)
$bar->advance();
$bar->setMessage('Database imported');
} catch (RemoteException $e) {
$this->errorBlock(
[
'Unable to import database. Deploy code first using this command:',
'php craft copy/code/up',
]
);
return ExitCode::UNSPECIFIED_ERROR;
return $this->printAndExit($e);
}
} else {
// Step 3: Backup the remote database before importing the uploaded dump
Expand All @@ -100,21 +100,8 @@ public function run(?string $stage = null)
try {
$plugin->ssh->exec("php craft copy/db/to-file {$backupFile} --interactive=0");
$bar->advance();
} catch (CraftNotInstalledException $e) {
$this->errorBlock(
[
'Unable to import database. Deploy code first using this command:',
'php craft copy/code/up',
]
);
return ExitCode::UNSPECIFIED_ERROR;
} catch (PluginNotInstalledException $e) {
$this->errorBlock(
[
'The plugin seems not to be installed on fortrabbit. Deploy code first using this command:',
'php craft copy/code/up',
]
);
} catch (RemoteException $e) {
return $this->printAndExit($e);
}

// Step 4: Import on remote
Expand All @@ -139,4 +126,31 @@ public function run(?string $stage = null)

return ExitCode::OK;
}

protected function printAndExit(RemoteException $exception): int
{
if ($exception instanceof CraftNotInstalledException) {
$this->errorBlock(
[
'Unable to import database. Deploy code first using this command:',
'php craft copy/code/up',
]
);
return ExitCode::UNSPECIFIED_ERROR;
}

if ($exception instanceof PluginNotInstalledException) {
$this->errorBlock(
[
'The plugin seems not to be installed on fortrabbit. Deploy code first using this command:',
'php craft copy/code/up',
]
);
return ExitCode::UNSPECIFIED_ERROR;
}

$this->errorBlock([$exception->getMessage()]);

return ExitCode::UNSPECIFIED_ERROR;
}
}
10 changes: 8 additions & 2 deletions src/EventHandlers/IgnoredBackupTablesHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ class IgnoredBackupTablesHandler
*/
public function __invoke(BackupEvent $event): void
{
// Since we sync assets, we keep assettransformindex
if (property_exists($event, 'ignoreTables')) {
$event->ignoreTables = array_diff($event->ignoreTables, [Table::ASSETTRANSFORMINDEX]);

// Include assettransformindex (do backup)
$ignoreTables = array_diff($event->ignoreTables, [Table::ASSETTRANSFORMINDEX]);

// Exclude resourcepaths (don't backup)
$ignoreTables[] = Table::RESOURCEPATHS;

$event->ignoreTables = $ignoreTables;
}
}
}
4 changes: 4 additions & 0 deletions src/Exceptions/CraftNotInstalledException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@

class CraftNotInstalledException extends RemoteException
{
/**
* @var string
*/
public $message = 'Craft is not installed on the fortrabbit App.';
}
17 changes: 17 additions & 0 deletions src/Exceptions/RemoteException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,25 @@

namespace fortrabbit\Copy\Exceptions;

use Throwable;
use yii\base\Exception;

class RemoteException extends Exception
{
public function __construct($message = '', $code = 0, ?Throwable $previous = null)
{
parent::__construct($this->cleanMessage($message), $code, $previous);
}

protected function cleanMessage(string $message): string
{
// remove double new lines
$message = preg_replace("/[\r\n]+/", "\n", $message);

// strip after ∙ƒ
if ($endPos = strpos($message, '∙ƒ')) {
$message = substr($message, 0, $endPos);
}
return trim($message);
}
}
19 changes: 11 additions & 8 deletions src/Services/Ssh.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,25 @@ public function exec(string $cmd)
return true;
}

if (trim($process->getErrorOutput()) === 'Could not open input file') {
throw new CraftNotInstalledException(trim($process->getErrorOutput()));
}
$out = $process->getOutput();
$err = $process->getOutput();

if (stristr($process->getErrorOutput(), 'Unknown command')) {
throw new PluginNotInstalledException(
'The Craft Copy plugin is not installed on remote.'
);
if (stristr($out, 'Could not open input file')) {
throw new CraftNotInstalledException();
}
if (stristr($err, 'Could not open input file')) {
throw new CraftNotInstalledException();
}
if (stristr($err, 'Unknown command')) {
throw new PluginNotInstalledException();
}

throw new RemoteException(
implode(PHP_EOL, [
'SSH Remote error: ' . $process->getExitCode(),
'Command: ' . $process->getCommandLine(),
'Output:',
$process->getErrorOutput(),
$err,
])
);
}
Expand Down

0 comments on commit 3735d24

Please sign in to comment.