Auto-Deploy a Web-App / Vue.js app with Gitlab to Heroku

Ben Denger
4 min readSep 19, 2018

--

Currently, I am working on a Slack-App which we want to publish soon (stay tuned, open source stuff and free apps incoming..)
To do so, we also have to create a simple landing page with a call-to-action-button to install Slack and an FAQ/help-section.

We decided to create the website with Vue.js, publish it on Heroku, and use Gitlab for our common dev-procedures.

So let's start.

To implement a working CI/CD we need the following things:
1. A Vue app (have a look on the official Vue.js guide or this article by Sebastian Eschweiler if you don't know how or where to start)
2. A Heroku App where we can publish the website
3. A Gitlab repo where we manage our CI/CD

Part 1: Heroku

Since I assume that you already have a Vue.js app, we will start by preparing our Heroku app.
To Create a Heroku App, you have to create an account, go to your dashboard and click on “create new app”, there you can choose a name and where the app should be located.

To host the Website with Heroku, we have to serve the files over a web service. Therefore, create a new file called server.js locate it in the root folder of your app and paste the following lines:

const express = require('express');
const serveStatic = require('serve-static');
let app = express();

app.use(serveStatic(__dirname + "/dist"));

const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log('Listening on port ' + port)
});

To use express and serve-static, you also have to install the according modules, click here for express and here for serve-static.

When we first deploy our application, Heroku will identify the buildpack and set it to node.

Done!
There is not much more to do on the Heroku part of our app.

Part 2: Gitlab

Bildergebnis für gitlab

Now we move to Gitlab and implement the .gitlab-ci.yml file with which we define our build and deployment stage.
Create a file in the root folder of your project which is called .gitlab-ci.yml and paste the following lines:

stages:
- build
- deploy

build:
stage: build
image: node:8
script:
- npm install --progress=false
- npm run build
artifacts:
paths:
- dist/


deploy:
stage: deploy
image: "ruby:2.5"
script:
# install dpl:
- apt-get update -qy
- apt-get install rubygems ruby-dev -y
- gem install dpl
# deploy to heroku:
- dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY --skip_cleanup
environment:
name: develop
url: https://$HEROKU_APP_NAME.herokuapp.com
only:
- develop

At the beginning of the file, we declare the 2 stages we need, build(which creates our dist/ directory) and deploy(which deploys the project to Heroku)

The build stage installs the node modules and builds our dist/ folder with the production files.

This dist/ path is declared as an artifact so the files are cached between the different stages.

Our deploy stage installs RubyGems and dpl(dee-pee-ell, a deployment tool)
and deploys our project to Heroku,
I struggled pretty long with that because somehow the build process created my dist/ folder correctly, it was still there in the deploy stage, but somehow it didn’t get deployed to Heroku.
As stated in the documentation of dpl you can use different strategies for deploying:

API vs Git Deploy:
API deploy will tar up the current directory (minus the git repo) and send it to Heroku.
Git deploy will send the contents of the git repo only, so may not contain any local changes.

So when I add the dist directory to my .gitignore it should work fine, but somehow it didn’t. That's why I’ve added the — skip_cleanup flag to prevent dpl from staging all files in their prepare deployment task.

Last but not least we have to add our variables in the Gitlab CI/CD Settings.
Navigate to your settings, click CI/CD and expand variables where you create the variable HEROKU_APP_NAME containing the name of your app and HEROKU_API_KEY which contains your API token which you find under https://dashboard.heroku.com/account in the bottom of your account settings.
Be careful with regenerating this key, because every app that uses this key, could stop working/ deployments using this key will fail when you don’t update them (I am telling you this because I had some issues with randomly failing builds until I realized this key is bound to the account, not the app).

Our next step is simple:
Do what you did before and keep coding, our Continuous Integration process will take care of the deployment.

--

--