GitLab Review Apps let you deploy every feature branch to a live, temporary environment so you can see your changes before merging.
Let’s see it in action. Imagine you’re working on a new feature for a Rails application. You’ve made some code changes and want to test them visually.
First, you need to configure your .gitlab-ci.yml file. This is where you tell GitLab how to build and deploy your application.
stages:
- deploy
review_app:
stage: deploy
image: ruby:2.7
environment:
name: review/$CI_COMMIT_REF_SLUG
url: http://$CI_COMMIT_REF_SLUG.your-domain.com
script:
- echo "Deploying branch $CI_COMMIT_REF_NAME to review environment..."
- # Your deployment script goes here.
# This might involve building Docker images, copying files,
# or interacting with a cloud provider's API.
- echo "Review app deployed at http://$CI_COMMIT_REF_SLUG.your-domain.com"
only:
- branches
except:
- main
- master
In this configuration:
stage: deploy: This job belongs to thedeploystage.image: ruby:2.7: We’re using a Ruby image, assuming a Rails app. Adjust this to your application’s stack.environment: This is key.name: review/$CI_COMMIT_REF_SLUG: This assigns a unique name to the environment based on the branch name.$CI_COMMIT_REF_SLUGsanitizes the branch name for use in URLs and environment names.url: http://$CI_COMMIT_REF_SLUG.your-domain.com: This is the URL where your review app will be accessible. You’ll need to configure your DNS or ingress controller to point this subdomain to your deployment target.
script: This is where the magic happens. The commands here will be executed on the GitLab Runner. You’ll replace theechostatements with your actual deployment commands. This could involve:- Building a Docker image for your application.
- Pushing the image to a container registry.
- Deploying the container to a Kubernetes cluster, a PaaS like Heroku, or even a simple server.
- Running database migrations specific to this branch.
only: - branches: This job will run for all branches.except: - main - master: It will not run for themainormasterbranches, as those are typically for production deployments.
When you push a new branch, say feature/add-user-profile, to your GitLab repository, GitLab CI/CD will detect the review_app job. It will then execute the script. If your deployment script is set up correctly, it will deploy your application to http://feature-add-user-profile.your-domain.com.
The beauty of this is that each branch gets its own isolated, ephemeral environment. This means developers can test their changes without interfering with each other or the main development line. When the branch is merged or closed, you can configure GitLab to automatically tear down the review app, saving resources.
GitLab also provides integrations for this. For example, when a merge request is created for a branch that has a review app, GitLab can automatically add a comment with the URL to that review app. This makes it incredibly easy for reviewers to access and test the proposed changes.
The underlying mechanism relies on dynamic environments. GitLab tracks environments by name. When you use the environment keyword in your CI/CD configuration, you’re telling GitLab to manage a deployment under that specific environment. The $CI_COMMIT_REF_SLUG variable is crucial here, as it dynamically generates a unique environment name and URL for each branch. This allows for many concurrent review apps without manual intervention.
A common point of confusion is how the url in the environment block actually makes the app accessible. This isn’t magic; it’s a declaration to GitLab. Your deployment script must actually make the application available at that URL. This often involves configuring an ingress controller in Kubernetes to route traffic from the subdomain (feature-add-user-profile.your-domain.com) to your application’s pod, or setting up DNS records and web server virtual hosts on a traditional server.
The environment block also allows you to define actions for when an environment is stopped. You can add a when: manual or when: on_success to a separate job that triggers a teardown script, effectively destroying the review app and freeing up resources.
The next step in mastering dynamic deployments is understanding how to manage secrets and configurations for these ephemeral environments, ensuring each branch has the correct API keys or database credentials without exposing them universally.