Delta CLI

Delta CLI is an open source project started to improve development workflows at Delta Systems. Before Delta CLI, each project had its own ad-hoc shell scripts, Phing configuration files, git hooks, etc. When switching between projects, developers would have to learn the particular idiosyncracies of that project's deployment scripts. Beyond that, these scripts were typically written without robust error handling, logging or notifications. Delta CLI scripts have a handful of important properties that address these issues.

Environment Independence

Rather than having separate scripts for deploying to staging, production, etc., Delta CLI scripts can be run against any of the project's environments. This reduces errors caused by the deployment script for staging slowly drifting away from the production script.

Per-Step Error Checking

In a typical bash script, one step can fail completely and the script will continue running. This can cause unexpected results. In Delta CLI scripts, each step returns a result and by default script execution is halted immediately when a step fails.

Dry Runs

Being able to preview the changes you'll apply before running an actual deploy can be very valuable, but supporting this kind of feature in an ad-hoc script can be tricky. Delta CLI supports dry runs for many common actions, like rsync, but you can also support dry run mode on your custom steps and scripts.

Logging and Notifications

Deploys to non-dev environments are automatically logged and notifications are sent via Slack. Other built-in Delta CLI commands are also logged and send notifications when interacting with non-dev environments, including ssh:shell, ssh:install-key, scp, rsync, db:shell and db:restore. You can enable logging and notifications on your own custom scripts with a single line of code.

A Consistent Interface

Regardless of the project, a developer should be able to run delta deploy production to push their changes live. This should work across all Delta projects. The actual steps performed by Delta CLI during deployment may vary drastically depending upon the type of project, but the experience of the user performing the deploy should be the same. We may change the tools or mechanisms we use to get files from git to a remote environment but the command used to trigger the deploy should remain the same.

Installation

Delta CLI is installed with Composer. First, you'll need to install Composer globally on your machine. Once Composer is available, you can install Delta CLI with the following command:

$ composer global require deltasystems/delta-cli

Finally, you'll want to adjust your shell's $PATH so that you can run delta from anywhere on your system. For a full walkthrough of this installation process, watch this 3-minute YouTube video.

Updating Delta CLI

You update to newer versions of Delta CLI with Composer:

$ composer global update

If you're trying to install a new major version of Delta CLI (e.g. you're going from 2.x to 3.x), you may need to require it via Composer:

$ composer global require deltasystems/delta-cli

Configuring a Project

You can run some Delta CLI commands immediately after installing it without any configuration whatsoever. However, you'll typically want to provide a delta-cli.php configuration file for your project. To get started, run this command in the root folder of your project:

$ delta create-project-config

create-project-config will ask you some questions about your project and generate SSH keys for your project. If you already have SSH keys, you can configure Delta CLI to use them, but it's generally easiest to have them in the default location and managed by Delta CLI. If you're configuring Delta CLI for a WordPress project, see the WordPress section of these docs for more details.

For other projects, you'll likely want to consult the environments and deploying sections for advice on configuring those aspects of your project.

Creating Your Delta API Account

The first time you run a Delta CLI command that interacts with Delta API, you'll be prompted to login or create your account. To create an account, you just need to provide a deltasys.com email address. An invite will be sent to your address. Using the code provided in that email, you'll be able to set your account password. Your Delta API key will be stored in your home folder and you will not need to authenticate again on that machine.

Some Basic Concepts

  1. If you just run delta, you'll get a list of the available commands. This will include all the built-in commands and your own custom scripts added in your delta-cli.php file.
  2. Every command includes a --help mode. This will display some brief documentation about the options that command supports. If you forget the required options on a command, you can leave them off and Delta CLI will automatically display this help information.
  3. With few exceptions, commands in Delta CLI are multi-step scripts. Delta CLI provides some tools for reviewing and manipulating those steps in the --list-steps and --skip-step options. --list-steps will list all the steps in your script. You can take any of those steps and pass them to --skip-step as needed. You can skip as many steps as needed. Generally, you'll want to run every step, but a service used by one step may be down or you may know a given step is counter-productive in your situation.

At Delta, we typically use three different types of environments: development, staging and production. A development environment is a sandbox for an individual developer. In a development environment, you may be running uncommitted code, experimenting with various approaches to your problem and using a variety of debugging tools. Staging is meant to mimic production as closely as possible and is often shown to clients or QA in preparation for a production deploy. If the production environment will force SSL, staging should, too. If production will use a certain kind of caching strategy, staging should, too. And production, of course, is your live site.

In Delta CLI, then, the key distinction is whether an environment is a dev environment or not. If it's a dev environment, certain checks and best practices can be relaxed. For example, on a dev environment, Delta CLI will not ensure that you've committed all your code before running the deploy script. Further, logging and notifications are typically disabled on dev environments. From the perspective of Delta CLI, however, staging and production as essentially equivalent unless you configure them differently.

list-environments

The list-environments command will show you all the environments your project currently has available. Out of the box, you'll see one or two environments by default: vpn and vagrant.

$ delta list-environments
+---------+-----------------------------+---------------------+
| Name    | Host(s)                     | Is Dev Environment? |
+---------+-----------------------------+---------------------+
| vpn     | vpn.deltasys.com            | No                  |
| vagrant | 127.0.0.1                   | Yes                 |
| staging | staging.deltasys.com        | No                  |
| joe-dev | remote-dev-box.deltasys.com | Yes                 |
+---------+-----------------------------+---------------------+

Adding an Environment to Your Project

To add an environment to your project, you'll edit your delta-cli.php file. Once added, they'll show up in list-environments and be available for use in any command that takes an environment as an argument.

Take note of a few things in the above example. First, staging is using a custom SSH key rather than the default generated by Delta CLI. The other environments do not have to specify the location of their SSH key because Delta CLI will default to looking in the ssh-keys folder automatically. Second, the dev-jane environment calls setIsDevEnvironment(true) so that Jane can push her changes to dev without sending notifications to everyone on the team or having to first commit her code. Finally, on both the production and staging environments, we're calling setGitBranch() to tie those environments to a specific branch in git. If we attempt to perform a deploy while on any other branch, Delta CLI will stop us. This prevents you from accidentally pushing your develop branch to production, for example.

Installing SSH Keys for an Environment

To authenticate with an environment, you'll need to install your project's SSH keys. You'll be prompted for the SSH password. After the key is installed, you'll never need to enter the password for that environment again.

$ delta ssh:install-key [environment-name]

Quickly Open an Environment in Your Browser

Sometimes dev and staging environments can have long or difficult to remember URLs. Delta CLI can generally detect the URL for an environment automatically and open it in your browser.

$ delta open [environment-name]

If for some reason your environment's browser URL, which typically differs from the hostname used for deploys, cannot be detected or is different than what you'd prefer, you can set it manually on a per-environment basis.

Managing APPLICATION_ENV

Many Delta projects use the APPLICATION_ENV environment variable to indicate to the application which environment should be loaded, for example, from the configuration file. Delta CLI assumes the the APPLICATION_ENV for an environment is the same as the environment's name. Delta CLI will set the APPLICATION_ENV environment variable accordingly when running SSH commands in that environment. If your APPLICATION_ENV needs to differ from the environment, you can call setApplicationEnv() on your environment to adjust it.

Cleaning up our deploy process was the original motivation behind Delta CLI. Since then, we've worked to improve other developer workflows as well, but deploys are still central to what Delta CLI does. A good deploy process is predictable, repeatable, easy, auditable and logged.

Predictability with Delta CLI deployments starts with the interface remaining consistent across a wide range of projects. Every project at Delta should be deployed with:

$ delta deploy [environment-name]

If we're talking about a WordPress project, we have one strategy for handling that deploy script. For other projects, the actual steps in that script may vary drastically from the WordPress script. However, the developer performing the deploy is running the same command. Further, the process is more predictable and understandable because the developer can use the --list-steps and --dry-run options to better understand what will happen when they deploy.

Once a deploy is done, it is automatically logged and notifications are sent via Slack. Developers can review these logs easily to see when a deployment was last made.

$ delta log --environment=production --script=deploy -v
deploy (production)
Run By: [email protected]
Date:   Wed Feb 1 2017 16:31

git-status-is-clean completed successfully.
git-branch-matches-environment completed successfully.
fix-ssh-key-permissions completed successfully.
log-and-send-notifications is ready to run at the end of this script.
rsync-www-to-httpdocs completed successfully on zeta.tripointhosting.com.

---

deploy (production)
Run By: [email protected]
Date:   Wed Feb 1 2017 13:49

git-status-is-clean completed successfully.
git-branch-matches-environment completed successfully.
fix-ssh-key-permissions completed successfully.
log-and-send-notifications is ready to run at the end of this script.
rsync-www-to-httpdocs completed successfully on zeta.tripointhosting.com.

In the above example, we're grabbing the logs for deploy runs on the production environment. We're also using -v to get the results of each step. We could use -vv to be even more verbose, displaying all the files that were transferred and the output that was generated by each step.

You can paginate log output using any Unix pager. When doing so, use the --colors option on Delta CLI to maintain the pretty, colorful output.

$ delta log --colors | less -R

Out-of-the-box Delta CLI will also perform some other checks prior to deploying your code. It will check both that your git status is clean (meaning that you have committed and pushed your code) and that you're on the correct branch of your repo.

Most projects will do the work of actually transferring files to the remote environment with rsync. You can learn more about adding steps, including rsync steps, to your project in the Custom Scripts section of these docs. This approach has some advantages: you don't need a clone of the repository on the remote environment, the dry-run functionality of rsync allows you to sanity check your deploy before you've moved any files into place, etc.

Ultimately, though, the actual mechanism for getting the files into place is less important than the overall experience being consistent and predictable. You could just as easily do a pull on a remote shallow clone of your repository, use a tool like Deployer from your Delta CLI script or do an API call to a service like CodeShip. If you'd like to better integrate any other methods of getting your code onto a remote environment, additional types of steps could be added to Delta CLI to make them as easy as possible to integrate.

As we go forward, we'll be adding more features to Delta CLI to make deploys better. Automatic git tagging on non-dev environment deploys is coming soon. And we also have plans for integrating Composer autoloading optimization, which should offer pretty big performance gains on our larger applications.

db:list

List all the databases present in an environment. Delta CLI will automatically detect databases configured in TriPoint Hosting .website_info files, WordPress wp-config.php files, DeltaZend config files or Dewdrop config files. If your application uses one of those common configuration formats, you shouldn't need to perform any configuration in your delta-cli.php file.

If your project uses some other configuration format, however, you can still add your database manually.

$ delta db:list [environment-name]
✓ find-databases completed successfully on staging.deltasys.com.
+-------------------+-----------+----------+----------+----------+
| DB Name           | Host      | Username | Password | Type     |
+-------------------+-----------+----------+----------+----------+
| example_database  | localhost | username | password | mysql    |
+-------------------+-----------+----------+----------+----------+
✓ list-databases completed successfully.

db:shell

db:shell drops you into a mysql or psql shell for your database.

$ delta db:shell [environment-name]
✓ find-databases completed successfully on 127.0.0.1.
✓ open-db-shell completed successfully.
  Opening database shell on vagrant.
+--------------------------------------------+----------------------------+
| Display Tables                             | \dt+                       |
| Display Columns from a Table               | \d [table-name]            |
| Automatically Enable Expanded Display Mode | \x auto                    |
| Open Editor for More Complex Queries       | \e                         |
| Display Help                               | \?                         |
| Turn on Timing of All Commands             | \timing                    |
| Run Query Repeatedly and Show Results      | \watch [number-of-seconds] |
| Connection Information                     | \conninfo                  |
| Quit                                       | \q                         |
+--------------------------------------------+----------------------------+
example=>

db:dump

Dump a database. The dump file will be placed on your local filesystem rather than on the remote environment. This ensures that we're not eating up disk space on the remote server or leaving database dumps available there unnecessarily. After creating the dump, you can use db:restore to use it.

$ delta db:dump [environment-name]
✓ find-databases completed successfully on 127.0.0.1.
↷ log-and-send-notifications was skipped because vagrant is a dev environment.
✓ dump-db-from-vagrant completed successfully on 127.0.0.1.
  127.0.0.1
    Successfully created database dump in dump-20170130-0229PM-from-vagrant.sql.

db:restore

Restore a database from a dump file. Prior to performing the restore, Delta CLI will also create a dump of the existing database as a backup. This will ensure you still have the original database if you accidentally restore to the wrong environment, for example.

$ delta db:restore [environment-name] [dump-file-location]
✓ find-databases completed successfully on 127.0.0.1.
↷ log-and-send-notifications was skipped because vagrant is a dev environment.
↷ sanity-check-potentially-dangerous-operation was skipped because vagrant is a dev environment.
✓ dump-db-from-vagrant completed successfully on 127.0.0.1.
  127.0.0.1
    Successfully created database dump in dump-20170130-0236PM-from-vagrant.sql.
✓ empty-database completed successfully on 127.0.0.1.
✓ restore-db-to-vagrant completed successfully on 127.0.0.1.
  127.0.0.1
    Successfully ran SQL file dump-20170130-0229PM-from-vagrant.sql in vagrant.
If you attempt to run db:restore with an environment that is not a dev environment, Delta CLI will stop you and require that you re-run the command with a random authorization code. This is intended to prevent accidental data loss on non-dev environments.

db:copy

db:copy is essentially just a combination of db:dump and db:restore. It'll run db:dump on one environment. Once done, the resulting dump file is immediately restored on another environment.

$ delta db:copy [source-environment-name] [destination-environment-name]
✓ configure-environments completed successfully.
✓ db:dump completed successfully.
  ✓ find-databases completed successfully on staging.deltasys.com.
  ✓ log-and-send-notifications is ready to run at the end of this script.
  ✓ dump-db-from-staging completed successfully on staging.deltasys.com.
    staging.deltasys.com
      Successfully created database dump in dump-20170130-0221PM-from-staging.sql.
  Logging and sending notifications via Delta API...
✓ db:restore completed successfully.
  ✓ find-databases completed successfully on 127.0.0.1.
  ↷ log-and-send-notifications was skipped because vagrant is a dev environment.
  ↷ sanity-check-potentially-dangerous-operation was skipped because vagrant is a dev environment.
  ✓ dump-db-from-vagrant completed successfully on 127.0.0.1.
    127.0.0.1
      Successfully created database dump in dump-20170130-0221PM-from-vagrant.sql.
  ✓ empty-database completed successfully on 127.0.0.1.
  ✓ restore-db-to-vagrant completed successfully on 127.0.0.1.
    127.0.0.1
      Successfully ran SQL file dump-20170130-0221PM-from-staging.sql in vagrant.
If you attempt to run db:copy with a destination environment that is not a dev environment, Delta CLI will stop you and require that you re-run the command with a random authorization code. This is intended to prevent accidental data loss on non-dev environments.

db:search-and-replace

Substitute a replacement string for a given search string throughout a database. This is generally most useful when copying a WordPress database from one environment to another. Using this command, you can replace the hostname from the previous environment with the new hostname. This command respects PHP serialization so the string lengths in any PHP serialized data in a WordPress database will automatically be adjusted as well.

$ delta db:search-and-replace [environment-name] [search-string] [replacement-string]
↷ sanity-check-potentially-dangerous-operation was skipped because vagrant is a dev environment.
✓ find-databases completed successfully on 127.0.0.1.
✓ generate-search-and-replace-sql completed successfully on 127.0.0.1.
  127.0.0.1
    Generated SQL to replace the search string 8813 times.
✓ restore-grafs-db-to-vagrant completed successfully on 127.0.0.1.
  127.0.0.1
    Successfully ran SQL file /delta/delta-cli-tools/.delta-cli-search-and-replace588fae5d788ec4.89200504.sql in vagrant.
✓ remove-sql-file completed successfully.
When running db:search-and-replace on a non-dev environment, Delta CLI will stop you and ask that you re-run the command with a random authorization code. This is intended to prevent accidental content changes on production databases.

db:tunnel

Open an SSH tunnel for an environment. This is useful if you want to connect to a remote database in a GUI like MySQL Workbench or PGAdmin.

$ delta db:tunnel [environment-name]
✓ find-databases completed successfully on staging.deltasys.com.
You can now configure your database application to connect to the tunnel using
the following information.

+----------+------------------+
| Host     | localhost        |
| Port     | 2129             |
| Username | example          |
| Password | R3a11yG00d!      |
| DB Name  | example          |
+----------+------------------+

Press enter to close the tunnel when you are ready to disconnect...

db:diagram

This command will generate a simple diagram of your database using Graphviz. It's not the prettiest diagram, but it gets the job done. You'll need the Graphviz dot command installed to run this.

Working with projects with multiple databases

Most projects have a single database. When that's the case, the above commands work without requiring you to specify the database you want to work with. If your project's environments have multiple databases, however, you'll need to specify which one you want to work with when running these commands. To do so, you can use a combination of the --database and --database-type options. For example, if your environment has two databases named "database_one" and "database_two", you can open a shell with the following command:

$ delta db:shell [environment-name] --database=database_one

There are a variety of logs that may be important sources of information when troubleshooting a problem. If you're not aware of all the locations where an application logs information, you may struggle to be productive on a new project. Delta CLI will find logs in all the typical locations for Delta projects.

logs:list

List all the logs available in an environment. The output will also tell you whether the logs will be watched by default when running logs:watch.

$ delta logs:list [environment-name]
✓ find-logs completed successfully on staging.deltasys.com.
+----------------------+----------------------+-----------------------------------------------------+------------------------+
| Name                 | Host                 | Location                                            | Is Watched By Default? |
+----------------------+----------------------+-----------------------------------------------------+------------------------+
| apache-error-log     | staging.deltasys.com | logs/error_log                                      | Yes                    |
| apache-access-log    | staging.deltasys.com | logs/access_log                                     | No                     |
| dewdrop-monolog      | staging.deltasys.com | zend/logs/staging.log                               | Yes                    |
| stickler-log         | staging.deltasys.com | delta_log table of the asdf_gh database.            | Yes                    |
| dewdrop-activity-log | staging.deltasys.com | dewdrop_activity_log table of the asdf_gh database. | Yes                    |
+----------------------+----------------------+-----------------------------------------------------+------------------------+
✓ list-logs completed successfully.

logs:watch

Watch your logs for updates. Delta CLI will continually output changes from the logs to your terminal, similarly to the Unix "tail -f" command. Not all logs are watched by default. If a log is rarely useful for troubleshooting, it will be skipped by default. If you'd like to watch these logs as well, you can use the --include=[log-name] or --include-all options.

$ delta logs:watch [environment-name]
stickler-log <staging.deltasys.com>
[1983-12-28 12:00] ERROR: You should have been watching the logs!
apache-error-log <staging.deltasys.com>
[2000-01-01 00:00] 404 /important-page-gone-missing
dewdrop-monolog <staging.deltasys.com>
[2038-01-19 03:14:08] End of an epoch.

ssh:shell

Open an SSH shell on a remote environment. If there are multiple hosts in an environment, you'll need to specify which host you want to access using the --hostname option. This option will do fuzzy matching of your host names. So, if you have two hosts in your environment called "app1.cluster.com" and "app2.cluster.com", you can just pass "app1" to the --hostname option rather than typing "app1.cluster.com" in full.

$ delta ssh:shell [environment-name]
✓ log-and-send-notifications is ready to run at the end of this script.
✓ fix-ssh-key-permissions completed successfully.
✓ open-ssh-shell completed successfully.
  Opening SSH shell to 'staging.deltasys.com' on staging.
Logging and sending notifications via Delta API...
Last login: Thu Jan 26 17:08:05 2017 from c-72-2-24-229.example.net
[[email protected] ~]$

rsync

Perform an ad-hoc rsync between two environments. This is mostly useful when pulling files down from another environment. For example, you might want to pull WordPress file uploads down from another environment so that your dev environment more closely resembles staging or production. Pushing files to non-dev environments with ad-hoc commands rather than using the deploy script is highly discouraged.

$ delta rsync staging:httpdocs/wp-content/uploads/ wp-content/uploads/
✓ rsync-logs-to-rsync-example completed successfully on staging.deltasys.com.
staging.deltasys.com
    New File  cute-cat.jpg
    New File  even-cuter-cat.jpg
✓ log-and-send-notifications is ready to run at the end of this script.
Logging and sending notifications via Delta API...
If you're using an ad-hoc rsync to send files to a non-dev environment, Delta CLI will stop you and request that your re-run your command with an authorization code.

scp

Perform an ad-hoc scp between two environments. You'd generally use scp rather than rsync when you only need to transfer a single file. The two commands take the same arguments.

$ delta scp staging:logs/access_log ~/Desktop
✓ scp-file-from-remote completed successfully on staging.example.com.
✓ log-and-send-notifications is ready to run at the end of this script.
Logging and sending notifications via Delta API...
If you're using an ad-hoc scp to send files to a non-dev environment, Delta CLI will stop you and request that your re-run your command with an authorization code.

If you're working from anywhere other than Delta HQ, you'll likely be unable to connect to most remote production environments. In this case, Delta CLI offers a built-in VPN connection you can use to tunnel your traffic through a trusted IP address.

Installing Your Project's SSH Key on the VPN

Each project needs to add its SSH key to the VPN. To do so, run the following command in your project:

$ delta ssh:install-key vpn

When prompted, provide the password specified in this Teamwork Notebook.

Using the VPN

Once your project's SSH key is installed, you can use the VPN by adding the --vpn option to any Delta CLI command. For example, if you're attempting to access an SSH shell on a remote environment via the VPN, use:

$ delta ssh:shell production --vpn

Using the WordPress Template

When you first run create-project-config to configure your project, you'll have the opportunity to use the WordPress template. When you select the template, you're asked about which themes and plugins you'd like to sync during deployments. After answering those questions, you'll end up with a delta-cli.php file that looks something like the following:

This may seem kind of odd at first glance. Why not just sync the entire WordPress installation to the remote environment? Generally, we only push the specific themes and plugins we're developing for the current project during deploy. The Delta sysadmin team and the WordPress auto-updater take care of everything else. Especially on WordPress projects, Delta will often have a team of developers working actively on a release for a while but then not touching the codebase again until new client requests come in. During that time, the remote environment will receive core and plugin updates frequently. Further, resources like wp-config.php don't have straightforward affordances for configuring multiple environments, so it's possible to break a site by pushing a configuration file that is actually intended for another environment.

If you look more closely at your new deploy script with --list-steps, you'll see the following steps:

$ delta deploy [environment-name] --list-steps
backup (Ssh)
git-status-is-clean (GitStatusIsClean)
git-branch-matches-environment (GitBranchMatchesEnvironment)
fix-ssh-key-permissions (FixSshKeyPermissions)
log-and-send-notifications (LogAndSendNotifications)
sync-indicate-theme (Rsync)
sync-basetheme-theme (Rsync)
sync-gravity-speedy-listing-plugin (Rsync)
sync-incomplete-application-email-sender-plugin (Rsync)
change-upload-folder-permissions (AllowWritesToRemoteFolder)

Your deploy script is going to perform a backup on non-dev environments, do some standard Delta CLI housekeeping, sync up your selected plugins and themes, and finally ensure the uploads folder is writable. You can still add more steps to your deploy script with addStep(). For more information, check out the Custom Scripts section of these docs.

Pulling Uploads from a Remote Environment

It's often useful to grab the uploaded files from staging or production. This keeps your dev environment closer to production and avoids having to work in an environment with a bunch of broken links and images. You can use the built-in rsync command to do this.

$ delta rsync --delete production:httpdocs/wp-content/uploads/ wp-content/uploads/

The --delete flag in the above example will ensure that any uploads that have been deleted on production will also be deleted on your own environment. You can also use --dry-run to get a sense of what files may have been added to or changed on the remote environment before actually performing the transfer.

Copying a Database from a Remote Environment

You can use db:copy to grab a database from a remote environment. Once complete, run db:search-and-replace to replace the hostname of the remote environment throughout the database with the hostname of the environment you're copying to.

If you have the Delta Vagrant environment installed, Delta CLI will add it to your project automatically. You can SSH to it with ssh:shell, run all the database commands, etc — just like you would for a normal environment. Additionally, a number of scripts are available to make working with Vagrant easier. Because these scripts are specific to Vagrant, you don't need to specify the environment when running them.

vagrant:create-vhost

This command will create virtual host configuration files for both nginx and Apache, restart those services, and show you how to update your hosts file.

$ delta vagrant:create-vhost my-hostname.local ./www
✓ vagrant:check-environment completed successfully.
  ✓ vagrant-delta-folder-exists completed successfully.
  ✓ vagrant-vhosts-folder-exists completed successfully.
  ✓ vagrant-sudo-without-password completed successfully.
  ✓ vagrant-mysql-root-with-default-password completed successfully.
  ✓ vagrant-postgres-superuser-with-no-password completed successfully.
✓ check-apache-conf-already-exists completed successfully.
✓ check-nginx-conf-already-exists completed successfully.
✓ create-apache-conf completed successfully.
✓ create-nginx-conf completed successfully.
✓ vagrant:restart-services completed successfully.
  ✓ restart-apache completed successfully on 127.0.0.1.
  ✓ restart-nginx completed successfully on 127.0.0.1.
  ✓ restart-postgres completed successfully on 127.0.0.1.
  ✓ restart-mysql completed successfully on 127.0.0.1.

Add docs-example.local to your host operating system's hosts file.

On OS X or Linux, you can run the following command:
sudo bash -c "echo '127.0.0.1 docs-example.local' >> /etc/hosts"

Learn more about adding entries to your hosts file or using dnsmasq on Github at:
http://bit.ly/delta-cli-hosts-file
✓ display-hosts-file-help completed successfully.

In the above example, we've requested that the virtual host be configured to use my-hostname.local and serve files out of our project's www folder. Typically, you'll use a folder called "www" or "public" for your document root.

vagrant:create-mysql and vagrant:create-postgres

Create a database in your Vagrant environment. These commands only require that you specify a database name. You can optionally use --username and --password to specify a different username and password for your database. If you do not specify a username and password, however, it will just make the username and password identical to the database name. That's a fairly common approach on local dev environments at Delta. You'll still need to configure your application to use the new database before the Delta CLI database commands will be able to see it. See the db:list docs for more information.

$ delta vagrant:create-postgres my_database
✓ vagrant:check-environment completed successfully.
  ✓ vagrant-delta-folder-exists completed successfully.
  ✓ vagrant-vhosts-folder-exists completed successfully.
  ✓ vagrant-sudo-without-password completed successfully.
  ✓ vagrant-mysql-root-with-default-password completed successfully.
  ✓ vagrant-postgres-superuser-with-no-password completed successfully.
✓ check-if-database-already-exists completed successfully.
✓ create-user completed successfully on 127.0.0.1.
  127.0.0.1
    CREATE ROLE
✓ create-database completed successfully on 127.0.0.1.
  127.0.0.1
    CREATE DATABASE
✓ drop-public-schema completed successfully on 127.0.0.1.
  127.0.0.1
    DROP SCHEMA
✓ create-public-schema completed successfully on 127.0.0.1.
  127.0.0.1
    CREATE SCHEMA

vagrant:check-environment

This script runs some checks to ensure your Vagrant environment is configured correctly. Mostly, this is ensuring that Delta CLI can run sudo in Vagrant without a password, access superuser accounts for MySQL and Postgres, etc.

$ delta vagrant:check-environment
✓ vagrant-delta-folder-exists completed successfully.
✓ vagrant-vhosts-folder-exists completed successfully.
✓ vagrant-sudo-without-password completed successfully.
✓ vagrant-mysql-root-with-default-password completed successfully.
✓ vagrant-postgres-superuser-with-no-password completed successfully.

vagrant:backup-dbs

This command will backup all your MySQL and Postgres databases. MySQL's dump will be at /delta/mysql.sql. The Postgres dump will be at /delta/postgres.sql. If you ever need to destroy and re-build your Vagrant environment, you can run this command before doing so.

$ delta vagrant:backup-dbs
✓ backup-mysql completed successfully on 127.0.0.1.
  127.0.0.1
    -- Warning: Skipping the data of table mysql.event. Specify the --events option explicitly.
✓ backup-postgres completed successfully on 127.0.0.1.
✓ output-status completed successfully.
  Postgres databases are in /delta/postgres.sql.  MySQL databases are in /delta/mysql.sql.

To restore these databases in your re-built Vagrant box, you'll run the following commands:

$ delta ssh:shell vagrant
[[email protected] ~]$ psql -U postgres < /delta/postgres.sql
[[email protected] ~]$ mysql --user=root --password=delta < /delta/mysql.sql

vagrant:restart-services

This command will restart important services in your Vagrant box.

$ delta vagrant:restart-services
✓ vagrant:check-environment completed successfully.
  ✓ vagrant-delta-folder-exists completed successfully.
  ✓ vagrant-vhosts-folder-exists completed successfully.
  ✓ vagrant-sudo-without-password completed successfully.
  ✓ vagrant-mysql-root-with-default-password completed successfully.
  ✓ vagrant-postgres-superuser-with-no-password completed successfully.
✓ restart-apache completed successfully on 127.0.0.1.
  127.0.0.1
    Stopping httpd: [  OK  ]
    Starting httpd: [Wed Feb 01 09:34:19 2017] [warn] module status_module is already loaded, skipping
    httpd: apr_sockaddr_info_get() failed for vagrant-centos64.vagrantup.com
    httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
    [  OK  ]
✓ restart-nginx completed successfully on 127.0.0.1.
  127.0.0.1
    Stopping nginx: [  OK  ]
    Starting nginx: [  OK  ]
✓ restart-postgres completed successfully on 127.0.0.1.
  127.0.0.1
    sudo: /etc/init.d/postgresql-9.4: command not found
    Stopping postgresql-9.5 service: [  OK  ]
    Starting postgresql-9.5 service: [  OK  ]
✓ restart-mysql completed successfully on 127.0.0.1.
  127.0.0.1
    Stopping mysqld:  [  OK  ]
    Starting mysqld:  [  OK  ]

vagrant:set-path

Delta CLI can typically detect the location of your Vagrant environment and its SSH keys automatically. However, sometimes "vagrant global-status" will stop correctly reporting all your Vagrant boxes following an upgrade. To work around this problem, you can manually set the path to your Vagrant box. Your path will be the same folder that contains your Vagrantfile.

$ delta vagrant:set-path [path-to-your-vagrant-box]

You can write custom scripts in your delta-cli.php file.

$ delta hello-world
✓ echo-hello-world completed successfully.
  Hello, world!

In our hello-world script, we just passed a string to addStep(). Delta CLI interprets that as a local shell command. When running a shell command, the success or failure of the step depends upon the exit status of that command. Like in Unix generally, an exit status of zero indicates success and any other status indicates failure.

We could accomplish this with a PHP callable instead of a shell command as well.

$ delta hello-world
✓ php-closure completed successfully.
  Hello, world!

In this case, we've passed a PHP function to addStep(). A step consisting of a PHP function succeeds if no exception is thrown. If you'd like more control over the result, you can also return a \DeltaCli\Script\Step\Result object. You can create the result object yourself or return it directly from another step object you run in your callback. Any output generated by the function is captured and displayed after the function completes.

Note that we've not executed anything at all at the moment we call addStep(). We've added a step to the script, but nothing will be run until the script is actually executed.

Renaming a Step

In the above examples, Delta CLI generated a default name for the steps we added. You'll often want to rename a step so that the script's output is more descriptive. To do so, we can simply pass the step name as the first argument to addStep().

$ delta hello-world
✓ hello-banner-display completed successfully.
  Hello, world!

Note that the step is now referred to as "hello-banner-display" instead of "php-closure" in the Delta CLI output.

Interacting with Environments

There are many uses for running commands locally, but often in Delta CLI scripts you'll want to interact with a remote environment instead. To do so, we first need to require the environment on our script. Then, we can convert our script to use SSH instead of a local shell command.

$ delta hello-world staging
✓ hello-banner-display completed successfully on staging.deltasys.com.
  staging.deltasys.com
    Hello, world!

We've called requireEnvironment() on our script, so now we have to specify which environment we want it to run on. Our addStep() call is now receiving a step created by $project->ssh(). If we had multiple hosts in our staging environment, our SSH step would run on all of them by default. Delta CLI will check the exit status of the SSH commands and the step will pass or fail accordingly. Our script can now interact with remote environments without being hard-coded to a specific remote environment.

When you're working with environments, you'll sometimes have steps that only need to run on specific environments. In those cases, just call addEnvironmentSpecificStep() instead of addStep(). The first argument to addEnvironmentSpecificStep() is an environment name or an array of environment names. The other arguments remain the same as what you passed to addStep().

Other Types of Steps

Allow Writes to Remote Folder

Allow the web server user to write files to the given folder. This may be needed for folders that store uploaded files, logs or other files generated by your application.

Fix SSH Key Permissions

SSH requires that keys have fairly restrictive permissions before it will use them to start a session. This step will automatically apply those permissions changes. This is included in the deploy script by default to avoid confusing developers when they first clone your repository and attempt a deploy.

Git Branch Matches Environment

We strongly recommend calling setGitBranch() on non-dev environments to tie them to a particular branch in git. This will ensure that the developer is actually on the master branch, for example, when they're interacting with production. You can add this step to any custom scripts that might need a similar safety check.

Git Status Is Clean

If your script requires that all changes be committed and pushed before it is run, add this step.

Is Dev Environment?

If your script should only run on dev environments, add this step.

Kill Process Matching Name

Kill any processing matching the supplied name. This can be useful if your script needs to stop and restart a process when certain code changes, for example.

Log and Send Notifications

Log and send notifications about the results of your script.

PHP Callable Supporting Dry Run

Provide a second PHP callable that performs a non-destructive dry-run version of your step.

Transfer Files with rsync

Transfer files to a remote environment using rsync. There are several options available on rsync steps, allowing you to configure flags, excludes, etc. rsync steps will automatically exclude common OS and VCS cruft.

Sanity Check Potentially Dangerous Operations

Add this step to stop execution and require the developer to re-run with an authorization code. By default, these steps will be skipped on dev environments. Their purpose is primarily to prevent the user from accidentally running a destructive operation on non-dev environments.

Transfer Files with scp

Transfer files to a remote environment with scp.

Run Another Script

You can run another Delta CLI script as a step in your own custom script.

Shell Command Supporting Dry Run

Run a shell command and provide an alternate command that can be run when in dry run mode.

Run a Command over SSH

Run a shell command over SSH. You can also add an SSH step supporting dry runs.

Or, with dry run support:

Start a Background Process

This step will start a process in the background that will continue running after Delta CLI completes and disconnects. This is a quick and easy to achieve this, but you should probably use something a bit more robust like supervisord in production. This is often used in conjunction with killProcessMatchingName().