Since the dawn of package managers and transpiler languages, the lives of us, developers, have become a lot easier. And, at the same time, a lot harder. The application source no longer corresponds directly to what should be on the server in order to serve the website or -application.

Transpiler languages convert source code from one language to another. This is great when it helps you double your productivity (or find your higher self). This is less great when you want the transpiled files (i.e. build / dist assets) to end up on the server and realise you can't track them in version control because it introduces all kinds of unnecessary headaches when you're trying to merge in a commit written by your colleagues.

Package managers and their delightfully modular nature tend to introduce thousands of small files that often all need to end up on the remote server - one way or another. Now don't get me wrong, I love that installing an HTTP client library, nowadays, is just a matter of composer require guzzlehttp/guzzle and hitting enter, but transferring thousands of files to a host is often a painful, error-prone and time-consuming process.

Welcome to asset hell.

By now, every time you install a new dependency or update a resource you need to keep track of all these trivial details: "Did we already upload the latest vendor directory?", "Can we safely overwrite the dist folder on the server without breaking anything?".

You've found yourself in asset hell.

Running builds in-place with SSH

SSH has the potential to solve a lot of these problems. You can ship all your source files at once with a tarball or even git pull them to the server directly and install dependencies or transpile assets in-place. This introduces a whole different set of problems, however: maybe you don't have the required privileges to install binaries such as git or node, and how about downtime or errors that might occur while updating dependencies. Or perhaps you don't have SSH access at all.

If you do have SSH access, a reasonable approach to avoid running builds on your production server is to create a separate branch or repository, containing the generated sources. You'll set up the repository on the remote, build the app locally and push everything to the remote using this branch. It works, but it's not very pretty. Moreover, the solution mentioned before prevents your workflow from being entirely "hosted" - i.e., if you make a commit from your phone you'll still need to log into some machine somewhere to trigger the build.

Continuous integration, the painless way

This is where continuous integration, or CI, comes into play. Very broadly speaking, it allows you to run a procedure or set of procedures whenever some trigger or event is fired. There's even some tools catered specifically towards deployment.

With a combined 15+ years of experience in the field, we've tried numerous continuous integration and deployment automation services, and a lot of them are really good. But we felt they just weren't quite for us. Some of the ones we liked best didn't allow us to actually run install/build commands. Others had a user interface that was probably very intuitive from the programmer's point of view, but unfortunately just not quite right for our use cases. We felt like things that should have been accessible within one click were hidden away in a deep hierarchy of menus, while at the same time some details that we would hardly ever need to know were always there, cluttering up the UI.

We believe that the ideal deployment workflow consists of a hosted solution, whether that's self-hosted or a third party solution, so that a workstation is not required to deploy code. The source repository should contain sources only, and every build should be performed "from scratch" based on these sources. Furthermore, the solution should provide "declarative versions" (every commit or version tag corresponds to a release in a transparent way that requires no manual work) and a one-way data flow (releases are automatically propagated from the source to the server, so you won't have to touch files on the server).

We're offering a deployment solution that's just right for our own projects -- so who knows it might be helpful to you as well. Interested? Sign up for free.

A better way to deploy code

Get started for free

Free • Simple setup • Cancel any time

A better way to deploy code

Get started for free

Free • Simple setup • Cancel any time

A little bit about the author
Lead developer and co-founder of Launchdeck - Node.js, TypeScript and Docker nerd.