Update dependencies with Renovate
Tags: programming, tutorial, security, git
Published: 2021-01-13 11:02:38

Automate dependency updates with Renovate in CI pipeline on  Gitlab, Azure, Gitea, Bitbucket, or GitHub. Because almost every program contains dependencies that are not updated so often, as they should be.

> 🇨🇿 V češtině si lze článek přečíst na [kutac.cz](https://www.kutac.cz/pocitace-a-internety/aktualizace-zavislosti-s-renovate-botem)

---

Vulnerabilities were, are, and will be also in the best libraries and packages. Because of that, it is really important to do an update as soon as possible after releasing the fix. However, it is hard to do those checks manually. From Github, you might know [Dependabot](https://dependabot.com/).

But there is another option called [Renovate Bot](https://docs.renovatebot.com/), which can be **self-hosted** and supports a **wide range** of git platforms. 

# Renovate Bot in Gitlab CI

Renovate can handle dependencies for many languages with [managers](https://docs.renovatebot.com/self-hosted-configuration/). For example for Java, there are 2 possible managers supported - Gradle and Maven. It is not surprising, that Renovate offers tons of [configurable options](https://docs.renovatebot.com/configuration-options/).

> Following tutorial will inform about the usage of Docker image. However, there is a possibility to use directly the Renovate core written in [JavaScript](https://docs.renovatebot.com/self-hosting/#npmjs).

## Step 1 - New project with bot and pipeline

As a starting point, you need to create a new Gitlab project/repository. That will contain the base **Renovate pipeline**, which you can trigger automatically by **CI/CD Schedules**. The minimum configuration consists of the files below.

I highly suggest setting environment variables via `CI/CD Variables`, not hardcode them into the CI file. `RENOVATE_TOKEN` grants bot access into repositories and `GITHUB_COM_TOKEN` is used to download Release notes from Github. See how to create those tokens in [Getting started](https://docs.renovatebot.com/getting-started/running/#gitlab-ceee).

### Pipeline file `.gitlab-ci.yml`

```yaml
update_repositories:
  # I use concrete version here, Renovate updates itself as configured in config.js
  image: renovate/renovate:24.12.4
  # variables: # I highly suggest to set them via CI/CD Variables
  #   RENOVATE_TOKEN: ""
  #   GITHUB_COM_TOKEN: ""
  script:
    - docker-entrypoint.sh
  artifacts:
    when: always
    paths:
      - renovate.log.json
  only:
    - schedules
```

### Config of Renovate bot `config.js`

```js
module.exports = {
  onboardingConfig: { // This will be placed into repositories without config
    extends: ["config:base"],
  },
  platform: "gitlab",
  endpoint: process.env.CI_API_V4_URL, // Needed only for self-hosted Gitlab
  logFile: "renovate.log.json", // Path to log file, must be same as in .gitlab-ci.yml in artifacts
  // Author cannot be the same as any developer, the best is to have own account for Renovate bot
  // Optionally it is possible to change just email
  // See here: https://github.com/renovatebot/config-help/issues/839
  gitAuthor: "RenovateBot <pavel.kutac+renovate@gmail.com>",
  baseBranches: ["master"],
  assignees: ["pavel.kutac"], // New MR are assigned into this person(s)
  // All repositories where Renovate will operate
  repositories: [
    "pavel.kutac/renovate-bot", // Updating itself, ie version in .gitlab-ci.yml
    "pavel.kutac/docker-ftp-deployer",
    "pavel.kutac/kutac_cz",
  ],
};
```

#### Example of Renovate Onboarding MR

![Renovate Onboarding MR](https://dev-to-uploads.s3.amazonaws.com/i/mtauoeva8ct5nkohxyfh.png)

### Optionally `renovate.json` config file

The `renovate.json` file is required only in the repositories, which are checked by the Renovate bot. But because this bot will update itself, this file must be placed into the repo as well.

```js
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  // Enables Docker major updates, disabled by default
  "extends": ["config:base", "docker:enableMajor"], 
  "enabledManagers": ["gitlabci"], // Only 1 manager will be run
  "requiredStatusChecks": null,
  // If the update is not major, do the merge automatically
  "packageRules": [{ "updateTypes": ["minor", "patch", "pin", "digest"], "automerge": true }]
}
```

## Step 2 - Setting the Renovate per-repo

As above, the `renovate.json` file must be placed into all repositories, which are checked and updated by the Renovate bot - ie into all mentioned under the `repositories` key in `config.js`. The following config is taken from my personal portfolio.

```js
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [ "config:base" ],
  "prHourlyLimit": 0, // Unlimited MRs per hour
  "prConcurrentLimit": 0, // Unlimited opened MRs in every moment
  "baseBranches": [ "devel" ], // Base branch, MR is merged into this one
  "enabledManagers": [ "npm", "docker-compose", "dockerfile", "gitlabci", "composer" ],
  // Add labels to every MR based on language and update type
  "packageRules": [
    { "updateTypes": ["major"], "addLabels": ["SemVer Major"] },
    { "updateTypes": ["minor"], "addLabels": ["SemVer Minor"] },
    { "updateTypes": ["patch", "digest", "bump"], "addLabels": ["SemVer Patch"] },
    { "languages": ["php"], "addLabels": ["Lang PHP"] },
    { "languages": ["js"], "addLabels": ["Lang JS"] }
  ]
}
```

#### Open MRs created by Renovate with labels

![Open MRs created by Renovate with labels](https://dev-to-uploads.s3.amazonaws.com/i/nv1yvjzfcr2pflx9rjf2.png)

## Step 3 - Renovate behavior

When the Renovate bot is run, it checks if every repository contains per-repo config file `renovate.json` *(there are few other possible names)*. If the config is not present, it will first create **Onboarding MR** with that file. No other actions are done until this MR is merged and config is created.

The next step is to check if there are no version ranges, but all versions **are pinned**. It means that `"laravel/framework": "^8.0"` is replaced into `"laravel/framework": "8.21.0"`. See more why it is happening in [Version pinning](https://docs.renovatebot.com/dependency-pinning/#what-is-dependency-pinning) chapter. If there are some versions to pin, it will create **Pinning MR**. And as in the previous step, no further actions are executed until this MR is merged.

If all checks pass, Renovate will create Merge requests for libraries with newly published versions. If the library published a new minor and major version, Renovate will create **2 MRs**. And it is up to you which one will be merged. If the major MR is merged, in the next run Renovate will do **cleanup** and close another MR and remove the branch.

#### Detail of MR created by Renovate

![Detail of MR created by Renovate](https://dev-to-uploads.s3.amazonaws.com/i/csevp9r40dg88zcv6sej.png)

---

In my case, I set to run Renovate every 1st day of a month by Gitlab CI/CD Schedules. Then I do merges of all updates, tests, and deploy. I do not recommend to do automatically merges if the project is not fully tested. Otherwise, it can cause much more trouble, which does not worth it.