Deploy Previews for GitLab

Learn how to configure Deploy Previews using the Heroku CLI and GitLab Environments.
View as Markdown

Overview

Deploy Previews for GitLab are made possible through the Heroku CLI and GitLab’s Environments feature.

Whenever you open a merge request on your GitLab repository, Heroku will automatically spin up a disposable app, reflecting the changes proposed in your merge request.

GitLab Environments

  • GitLab’s environments allow you to track deployments dynamically.
  • Each merge request can have its own environment.
  • You need to define environments in your .gitlab-ci.yml file.
  • Ephemeral environments (like review apps) can be spun up and later torn down with a stop job (action: stop).

Heroku CLI

  • The Heroku CLI allows you to dynamically generate deployments.
  • Each Deploy Preview that is generated with the Heroku CLI will be tracked within GitLab Environments.
  • Please install the Heroku CLI before continuing with the setup process.

Setup and Configuration

Step 1: Generate a long-lived auth token with the Heroku CLI & store it in GitLab variables

After installing and logging in with the Heroku CLI you’ll need to generate a long-lived auth token.

  1. Run heroku authorizations:create to generate a token that expires in 1 year.
  2. Copy the token and also create a reminder to generate a new token before the current one expires.
  3. Back in GitLab — Navigate to Settings » CI/CD and expand the “Variables” section.
  4. Click “Add variable”, set visibility to “Masked and hidden”, set key to “HEROKU_API_KEY” (no quotes), with the value you copied from the CLI command earlier.
  5. Click “Add variable” to save it.

Step 2: If you don’t already have the variable HEROKU_GIT_URL for your production app configured, set that up now

Now that we’re going to be both publishing to your production application and dynamically generating Deploy Previews we want to make sure we have the HEROKU_GIT_URL variable configured correctly.

  1. Validate if the variable exists.
  2. If not, create the variable using the same settings as in the last step above. For the key you’ll use “HEROKU_GIT_URL” (no quotes) with the value being the Git URL of your production app.
  3. Your production application should reside within your new Heroku Team. To locate your Git URL you’ll need to navigate to your Heroku Dashboard and then click into your production app. From there you’ll click the “Settings” tab and your Heroku Git URL will be located there.
  4. After setting the HEROKU_GIT_URL variable we can move onto configuring the .gitlab-ci.yml file.

Step 3: New .gitlab-ci.yml configuration

With our variables configured correctly let’s setup the .gitlab-ci.yml to match the below configuration. Be sure to replace your-team-here references (theres only 1) with your actual team name provided earlier on during this process.

1stages:
2 - build
3 - deploy_main
4 - deploy_review
5 - cleanup
6
7variables:
8 HEROKU_APP_NAME: ks-$CI_PROJECT_NAMESPACE-$CI_PROJECT_NAME-$CI_MERGE_REQUEST_IID
9
10### Build Step for Production Deployments (main branch) ###
11Build_Main:
12 image: node:20
13 stage: build
14 script:
15 - npm install
16 - npm run build
17 cache:
18 key: knapsack-build
19 paths:
20 - node_modules
21 only:
22 - main
23
24### Production Deployments (main branch) ###
25Deploy_Main:
26 stage: deploy_main
27 before_script:
28 - echo "machine git.heroku.com login _apikey password $HEROKU_API_KEY" > ~/.netrc
29 script:
30 - git fetch
31 - git checkout main
32 - git remote add heroku $HEROKU_GIT_URL
33 - git push heroku main
34 only:
35 - main
36
37### Build Step for Review Apps (Merge Requests) ###
38Build_Review:
39 image: node:20
40 stage: build
41 script:
42 - npm install
43 - npm run build
44 cache:
45 key: knapsack-build
46 paths:
47 - node_modules
48 rules:
49 - if: $CI_MERGE_REQUEST_ID
50
51### Deploy Step for Review Apps (Merge Requests) ###
52Deploy_Review:
53 stage: deploy_review
54 before_script:
55 - curl https://cli-assets.heroku.com/install.sh | sh
56 - export HEROKU_API_KEY=$HEROKU_API_KEY
57 - git config --global user.email "ci@example.com"
58 - git config --global user.name "GitLab CI"
59 - echo "machine git.heroku.com login _apikey password $HEROKU_API_KEY" > ~/.netrc
60 - git fetch origin $CI_COMMIT_REF_NAME
61 - git checkout $CI_COMMIT_REF_NAME
62 script:
63 - heroku apps:info --app $HEROKU_APP_NAME || heroku apps:create $HEROKU_APP_NAME --team your-team-here
64 - heroku git:remote -a $HEROKU_APP_NAME
65 - git push heroku $CI_COMMIT_REF_NAME:main --force
66 - heroku ps:scale web=1
67 environment:
68 name: review/$CI_COMMIT_REF_SLUG
69 url: https://$HEROKU_APP_NAME.herokuapp.com
70 on_stop: Stop_Review
71 rules:
72 - if: $CI_MERGE_REQUEST_ID
73
74### Stop Review Step for Review Apps (Merge Requests) ###
75Stop_Review:
76 stage: cleanup
77 before_script:
78 - curl https://cli-assets.heroku.com/install.sh | sh
79 - export HEROKU_API_KEY=$HEROKU_API_KEY
80 script:
81 - heroku apps:destroy --app $HEROKU_APP_NAME --confirm $HEROKU_APP_NAME || echo "App not found, skipping cleanup"
82 environment:
83 name: review/$CI_COMMIT_REF_SLUG
84 action: stop
85 rules:
86 - if: $CI_MERGE_REQUEST_ID
87 when: manual

Step 4: Save the changes, push, and test!

Let’s get these changes merged in so we can test!

  1. After these changes are merged — let’s create a new branch with a minor change.
  2. Create an MR and verify the environment is created. Environments can be viewed via Operate » Environments.
  3. When the build completes you should be able to view your first Deploy Preview! 🚀
  4. Merge the MR and a couple things should happen:
    1. The Deploy Preview should destroy the review app within Heroku and clean up any resources used.
    2. The normal deploy to production should activate and move forward as expected. 🎉🎉🎉
  5. All done!