Software delivery is hard; plenty of people all over this planet are struggling with delivering software in their own controlled environment. They have invented great patterns that will build an artifact, then do some magic and the application is up and running.
When talking about continuous delivery, people invariably discus their delivery pipeline and the different components that need to be in that pipeline. Often, the focus on getting the application deployed or upgraded from that pipeline is so strong that teams forget how to deploy their environment from scratch.
After running a number of tests on the code, compiling it where needed, people want to move forward quickly and deploy their release artifact on an actual platform. This deployment is typically via a file upload or a checkout from a source-control tool from the dedicated computer on which the application resides. Sometimes, dedicated tools are integrated to simulate what a developer would do manually on a computer to get the application running. Copy three files left, one right, and make sure you restart the service. Although this is obviously already a large improvement over people manually pasting commands from a 42 page run book, it doesn’t solve all problems.
Like the guy who quickly makes a change on the production server, never to commit the change (say goodbye to git pull for your upgrade process) if you package your software there are a couple of things you get for free from your packaging system. Questions like: has this file been modified since I deployed it, where did this file come from, when was it deployed, what version of software X do I have running on all my servers; are easily answered by the same tools we use already for every other package on the system. Not only can you use existing tools, but you are also using tools that are well known by your ops team and that they already use for every other piece of software on your system.
If your build process creates a package and uploads it to a package repository which is available for the hosts in the environment you want to deploy to, there is no need anymore for a script that copies the artifact from a 3rd party location, and even less for that 42 page text document which never gets updated and still tells you to download yaja.3.1.9.war from a location where you can only find 3.2 and 3.1.8 and the developer that knows if you can use 3.2 or why 3.1.9 got removed just left for the long weekend.
Another, and maybe even more important thing, is the current sadly growing practice of having yet another tool in place that translates that 42 page text document to a bunch of shell scripts created from a drag and drop interface, typically that "deploy tool" is even triggered from within the pipeline. Apart from the fact that it usually stimulates a pattern of non reusable code, distributing even more ssh keys , or adding yet another agent on all systems. it doesn’t take into account that you want to think of your servers as cattle and be able to deploy new instances of your application fast.
Do you really want to deploy your five new nodes on AWS with a full Apache stack ready for production, then reconfigure your load balancers only to figure out that someone needs to go click in your continuous integration tool or deployment to deploy the application to the new hosts? That one manual action someone forgets?
Imvho Deployment tools are a phase in the maturity process of a product team. Yes, it's a step up from manually deploying software but it creates more and other problems. Once your team grows in maturity refactoring out that tool is trivial.
The obvious and trivial approach to this problem, and it comes with even more benefits. is called packaging. When you package your artifacts as operating system (e.g., .deb or .rpm) packages, you can include that package in the list of packages to be deployed at installation time (via Kickstart or debootstrap). Similarly, when your configuration management tool (e.g., Puppet or Chef) provisions the computer, you can specify which version of the application you want to have deployed by default.
So when you’re designing how you want to deploy your application, think about deploying new instances or deploying to existing setups (or rather, upgrading your application). Doing so will make life so much easier when you want to deploy a new batch of servers.