diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..516e1bc
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,17 @@
+# Changelog
+
+Notable changes to this project will be documented in this file.
+The format is based on [keep a changelog](http://keepachangelog.com/en/1.0.0/) principles
+and adheres to [semantic versioning](http://semver.org/spec/v2.0.0.html).
+
+## 1.1.0 - Unreleased
+
+* Add new `bin/magento mx:db:migrate` command that handles migrations seamlessly.
+
+## 1.0.1 - 2018-07-05
+
+* Remove the auto-generation of the `phinx.php` configuration file.
+
+## 1.0.0 - 2018-07-04
+
+* Initial release.
diff --git a/README.md b/README.md
index 1511098..0c791e2 100644
--- a/README.md
+++ b/README.md
@@ -117,9 +117,17 @@ We have access to 3 different setup helpers provided by Magento in each migratio
### Execute migrations
-When you are happy with your migration you can execute it as follows
+This module provides a new command that wraps up the whole DB migration process
- bin/phinx migrate
+ bin/magento mx:db:migrate
+
+The new command does the following:
+
+1. Checks if a `setup:upgrade` is required (e.g. if a 3rd party module was updated or Magento was upgraded)
+2. Runs `setup:upgrade` if it is required
+3. Runs `bin/phinx migrate`
+
+This should replace the `bin/magento setup:upgrade` command in your deployment and development workflow.
### Rolling back
diff --git a/etc/di.xml b/etc/di.xml
new file mode 100644
index 0000000..fb9a127
--- /dev/null
+++ b/etc/di.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ -
+ MX\PhinxMigrations\Console\Command\MigrateCommand
+
+
+
+
+
diff --git a/src/Console/Command/MigrateCommand.php b/src/Console/Command/MigrateCommand.php
new file mode 100644
index 0000000..fd7a28e
--- /dev/null
+++ b/src/Console/Command/MigrateCommand.php
@@ -0,0 +1,69 @@
+
+ */
+class MigrateCommand extends Command
+{
+ private const MIGRATE_TIMEOUT = 900;
+ private const PHINX_BIN = 'vendor/robmorgan/phinx/bin/phinx';
+
+ protected function configure()
+ {
+ $this
+ ->setName('mx:db:migrate')
+ ->setDescription('Migrates the database so it is ready for use with the current application code.');
+
+ $this->addOption(
+ 'keep-generated',
+ null,
+ InputOption::VALUE_NONE,
+ 'Prevents generated files from being deleted during migration.'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $dbStatusCommand = $this->getApplication()->get('setup:db:status');
+
+ $output->writeln('Checking if setup:upgrade is required...');
+ $exit = $dbStatusCommand->run(new ArrayInput([]), new NullOutput());
+
+ if ($exit === DbStatusCommand::EXIT_CODE_UPGRADE_REQUIRED) {
+ $output->writeln('A setup:upgrade is required, running...');
+ $setupUpgradeCommand = $this->getApplication()->get('setup:upgrade');
+
+ $setupUpgradeArgs = $input->getOption('keep-generated') ? ['--keep-generated' => true] : [];
+ $setupUpgradeCommand->run(new ArrayInput($setupUpgradeArgs), $output);
+ } else {
+ $output->writeln('No setup:upgrade required.');
+ }
+
+ return $this->runPhinxMigrate();
+ }
+
+ protected function runPhinxMigrate(): int
+ {
+ $phinx = new Process(sprintf('%s migrate', self::PHINX_BIN));
+
+ $phinx->setTimeout(self::MIGRATE_TIMEOUT);
+ $phinx->run(function ($type, $buffer) {
+ echo $buffer;
+ });
+
+ return $phinx->isSuccessful() ? Cli::RETURN_SUCCESS : Cli::RETURN_FAILURE;
+ }
+}