Automatic Dependency Updates Using Renovate on Mamikos Self-hosted GitLab
Background
Like the other usual frontend tech stacks, Mamikos has a lot of web applications that use Nodejs and their packages. As time goes on, a lot of our Node dependencies have security vulnerabilities and the dreadful of all: deprecated. To avoid these problems, we need to check and update each existing dependency. Without additional tools to automatically update the dependencies, that task will be very manual and will be very time consuming.
Because Mamikos is using self-hosted Gitlab, the most suitable tool for our needs is Renovate (Dependabot is still in WIP for Gitlab). Unfortunately, the tutorial for Renovate for self-hosted Gitlab is very rare and a little bit outdated. Therefore, this article was written and hopefully can provide a streamlined guide.
What are our expectations for implementing Renovate on Mamikos’ repos?
- Check dependencies version automatically and periodically
- Automatically assign MR assignee and reviewer
- Detect and update based on patch, minor, and major version changes
- Give informations if there’s package vulnerability
- Can be limited to only frontend tech stack (or only for
package.json
)
The initialization for this Renovate bot is quite puzzling because Renovate’s own documentation is too verbose so it’s very difficult to learn at first and there is an example but with very short explanation on Gitlab’s Renovate runner example.
Implementation
Based on the result of our research, here are the setup steps that we need to carry out:
1. Create a new repo on Gitlab for the Renovate bot
Simple enough, create an empty project/repository. This repo will be used to run and configure Renovate. Clone this new repo to our local machine.
2. Add new CI/CD variables on the Renovate bot repo
From our new repository on GitLab, open Settings → CI/CD → Variables menu and add these 3 new variables:
RENOVATE_TOKEN
: The value for this variable can be obtained from GitLab’s User Settings → Access Token menu. It’s advisable that this token should be generated from a specific Gitlab account that will be used for automation and that account must have access to the target repo.GITHUB_COM_TOKEN
: This token is used so the bot can retrieve the dependency’s changelog. The value can be obtained from Github Settings → Developer Settings → Personal access token menu.RENOVATE_EXTRA_FLAGS
: Filled with the name of the GitLab project that we want to check. If there’s more than one project, separate the project names with white space.
3. The Renovate Configurations
Create a renovate.gitlab-ci.yml
on the root directory of the Renovate Bot repo. This file will be used on the Gitlab pipeline setup. Here’s the content of the file:
variables:
RENOVATE_BASE_DIR: $CI_PROJECT_DIR/renovate
RENOVATE_ENDPOINT: $CI_API_V4_URL
RENOVATE_PLATFORM: gitlab
RENOVATE_ONBOARDING_CONFIG: '{"$$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"] }'
RENOVATE_OPTIMIZE_FOR_DISABLED: 'true'
RENOVATE_REPOSITORY_CACHE: 'enabled'
RENOVATE_LOG_FILE: renovate-log.ndjson
RENOVATE_LOG_FILE_LEVEL: debug
CI_RENOVATE_IMAGE: ghcr.io/renovatebot/renovate:37.279.3@sha256:fc6ab8d230170fd405a02aa29f8708d3c5dbb6f543a948671446235b479d0bd3
.renovate:
cache:
key: ${CI_COMMIT_REF_SLUG}-renovate
paths:
- renovate/cache/renovate/repository/
image: ${CI_RENOVATE_IMAGE}
script:
- renovate $RENOVATE_EXTRA_FLAGS
renovate:
extends: .renovate
stage: deploy
resource_group: production
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
artifacts:
when: always
expire_in: 1d
paths:
- '$RENOVATE_LOG_FILE'
Create a default.json
file and fill it with the Renovate configuration. For Mamikos' needs, we can break it down into:
- Only
develop
branch that needs to be checked on target repo
"baseBranches": [
"develop"
],
- Only
npm
andnvm
need to be checked
"enabledManagers": [
"npm",
"nvm"
],
- Create a “dependencies” label for merge requests created by Renovate
"labels": [
"dependencies"
],
"assignees": [
"roy"
],
"reviewers": [
"tri"
],
- Create merge requests for dependencies that have vulnerabilities
"vulnerabilityAlerts": {
"labels": [
"security"
]
},
- We want to create the merge requests manually because we need to check if our application can be built or not if the package is updated
"dependencyDashboardApproval": true,
If we combine the previous config, our default.json
content will be:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":dependencyDashboard"
],
"baseBranches": [
"develop"
],
"enabledManagers": [
"npm",
"nvm"
],
"labels": [
"dependencies"
],
"assignees": [
"roy"
],
"reviewers": [
"tri"
],
"vulnerabilityAlerts": {
"labels": [
"security"
]
},
"dependencyDashboardApproval": true,
}
4. Create a .gitlab-ci.yml
file
.gitlab-ci.yml
file is a configuration file that will be used to run the GitLab pipeline. The content of the file will be taken from the guide on Gitlab Renovate. The value for the project
will be the name of the Renovate bot repo, and the value for the file
is the previous step 3.
include:
- project: 'mamikos/renovate-runner-bot'
file: '/renovate.gitlab-ci.yml'
Finally, we have finished our configuration for the Renovate bot repository, we need to create the pipeline scheduler. (If you want to run pipeline without scheduler, you must add new rule in renovate.gitlab-ci.yml
file, or the pipeline won’t run at all.)
Here’s an example of our working pipeline:
Initializing Renovate on Existing Mamikos’ Projects
After the pipeline is triggered, Renovate will make a merge request on our target repository.
The content of this merge request is only a renovate.json
file. Because we already created and have a default.json
file, we need to edit this renovate.json
. We need to add a new .nvmrc
file to lock the project’s Node version and let Renovate know what’s the current Node version.
Using the local presets reference, the content of renovate.json
will be changed from:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
]
}
Into:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>mamikos/renovate-runner-bot"
]
}
And then, don’t forget to merge the MR.
Review the Dependency Dashboard by Renovate Bot
On the next triggered scheduled pipeline, Renovate will create an issue with “Dependency Dashboard” as the title.
As the title suggests, this issue will be our dashboard to decide which package we want to update, which MR(s) that Renovate already generated, and ignored MR or package.
After we checked the package checkbox that we wanted to update, we needed to wait for the Renovate bot scheduled pipeline to be triggered again.
After the pipeline is triggered, the Renovate will create an update package MR that we already checked previously:
What is the meaning of the Age, Adoption, Passing, and Confidence label? The explanation for these labels is on merge confidence Renovate documentation:
- Age: The age of the package
- Adoption: The percentage of this package’s users (within Renovate) who are using this release
- Passing: The percentage of updates that have passed tests for this package
- Confidence: The confidence level for this update
The confidence level is a result of the Renovate algorithm that can be used as a rough reference if the package is safe to be updated without manual checking.
Conclusion
Does the Renovate that we have set up meet the expectations that we mentioned in the background section of this article?
- Check dependencies version automatically and periodically ✅
Regular checking can be done using the GitLab pipeline scheduler. - Automatically assign MR assignee and reviewer ✅
Usingassignees
andreviewers
. configuration option. - Detect and update based on patch, minor and major version changes ✅
Renovate dashboard has separate checkboxes for minor and major versions. Unfortunately, Renovate can’t separate between patch and minor versions. - Information if there’s package vulnerability ❓
Even though there’s a configuration for vulnerability alerts, so far there’s no MR that’s related to vulnerability. - Can be limited to only frontend tech stack (or only for
package.json
) ✅
Using enabled managers configuration. For a more comprehensive list, you can check it on the supported managers’ documentation page.
Even though we already using Renovate, there are 3 things that must be done manually:
- Some dependencies have breaking changes update, so we must do manual checking in our local machine first.
- Can’t detect vulnerability at the sub-dependency level, so we must depend on Trivy and
resolutions
inpackage.json
. - Auto merge based on confidence level must use the Mend API key and it’s not free.
There are still many things that can be learned from Renovate, the configuration is so exhaustive. But for the current needs of Mamikos’ front end, it is sufficient for now.
Hopefully, this article helps those who want to set up Renovate configuration but feel overwhelmed by reading Renovate documentation. Cheers! 🍻