Before we get started with creating deployment tasks, we have to add a few Deployer settings.
Specifically, we need to tell it the URI of the Git repository to clone, which contains our application’s source code. And we also need to tell it how many releases to keep. This will be significant later, when we look at the cleanup command.
To do both of these, we call the
set function, which takes two arguments.
The first is the setting which we want to set, the second is the value of that setting. What’s great about Deployer, is that the settings are logically named.
set the URI of the Git repository, by calling
set and specifying
repository as the key, and the URI as the value.
I’ll then set the number of releases to keep, by again calling
set and specifying
keep_releases as the key, and
5 as the value.
This will ensure that Deployer cleans up any releases older than the latest five, assuming that we have at least that many available.
Tasks & Recipes
Now that we have our servers configured, we need to setup the tasks which will be run when the servers are contacted. There are a number of existing tasks in the composer recipe which I've imported.
We'll cover these a little bit later on. For the moment, lets look at how to write some custom tasks, just for our needs.
Specifically I'm going to create three tasks:
One to restart PHP FPM; One to restart Nginx; and the third to print a message to let me know everything's done.
Shouldn't be too hard - right? Let's do it.
A task requires two things:
- A name
- An anonymous function or PHP callable
The task name is how you'll refer to it, and the name you'll see in the tasks list when you run
You may remember the list of tasks from when we ran the command earlier. OK, so I'll call the
task() method, and give the first task a name of 'deploy:done'.
Note how it's composed of two parts, separated by a colon? This is important as it uses the text before the colon to group the command. The name itself isn't that important from a programmatic sense. But it's wise to give it a name which is both meaningful and intuitive.
That way, it'll make sense when users are looking for the right task to run. So make sure you think about that.
With that done, let's now add an anonymous function, to serve as the body of the task, which will call one of the in-built functions,
write(), to print out a simple string, which I'll set as "Deploy done!".
Now I'll do one last thing, which is to call the
desc() method and add a quick description. Whilst not strictly necessary, it's handy from a programmatic point of view to make it more descriptive as to what the task is for. What's more, it also turns up in the dep list, so that when a user's browsing the list of tasks, they can see it there as well.
Now let's look at one more task, one to reload Nginx.
This one's slightly more complicated, but not much. I'll quickly call tasks, and add the name, then get to the anonymous function body. Here I'll call another of the in-built methods,
run(), which executes a command.
In this case, I'm going to reload Nginx, by executing
sudo /usr/sbin/service php5-fpm reload. Sure, this is a bit of work, and it'd be great to have something like Ansible tasks where you just have to call a method like
reload-nginx, but that's not currently available.
And to be honest, it's not that much work to encapsulate a tested command.
There's one more command, which is to reload PHP FPM. But it's largely the same as reloading Nginx. So I'll quickly add that in.
There are several other available commands, which you can find documented under http://deployer.org/docs/functions.
There's ones to prompt the user for input, change the current working directory, and running commands locally. Definitely check out the documentation, so that you're fully abreast of what's on offer.
The Deploy Task
As with the other tasks, I'll call the task method, and specify the task name of deploy.
Deploy is a pre-defined task, which is something I want to draw attention to. There are any number of pre-defined tasks, and if you're not careful, you can inadvertently overwrite them. So be careful when choosing a name.
It might be helpful to use a custom prefix, such as your company name, or your twitter or IRC handle.
With that said, I'll specify the second argument as an array, then add in a series of task names. In this case, I'm making use of the pre-written tasks in the Composer Recipe.
Stepping through them:
- prepare & release: which prepare the server for deployment, creating a releases and a shared directory
- update_code: Which clones the specified git repository, making it the latest release directory
- vendors: Runs composer install, bringing in any external dependencies
- symlink: Creates a symlink named current which points to the latest release
- cleanup: Removes old releases and keeps the last five
I’ll then call the desc function to add a meaningful descriptor.
OK, so that's our tasks all take care of. Now let's look at hooking in to tasks, for some slightly more advanced functionality.
Deployer provides two hooks, these are
after(), which are available by the aptly named methods of the same name. They only require two things, a name and a task name to hook in to.
Starting to see that it's important to name tasks logically and intuitively?
As the name implies, here, when the task you've hooked in to is finished, the linked task will fire off. If you want to fire off a task before a job's run, then call
One thing to note is that you have to add hooks one at a time, in succession, as you can't add them all at once, as you might anticipate.
Now let's look at pulling a series of tasks together to make the main deploy task. This is another way in which you can create a task. It's a nice, logical, bundling of functionality.
And that's how to do it all, from start to finish.
Now yes, there are more options, which we've touched on through the course of this series, but what we've covered is enough to get up and running and do the first deploy.