Files
renovate/lib/modules/platform/gitlab
Sebastian Poxhofer 58d9a01dd5 feat(platform): one "read repo file at ref" helper per host (#46190)
* refactor(util): one "read repo file at ref" helper per host

The "fetch a single file from a repository at a ref" logic was implemented
separately in the platform, preset and changelog layers for every host, and
`lib/config/presets` reached into `lib/modules/platform` to reuse the Gitea
client and its contents helper.

Add per-host util modules that own the URL shape, the response schema and the
decoding, taking the caller's own `Http` instance so the host type stays with
the calling layer:

- `lib/util/gitea/contents.ts` (shared by Gitea and Forgejo): the `RepoContents`
  and `ContentsListResponse` schemas, `getRepoFile()` and `listRepoDir()`
- `lib/util/github/contents.ts`, `lib/util/gitlab/files.ts`,
  `lib/util/bitbucket/files.ts`: `getRepoFile()`

Callers rewired: `getRawFile` for github/gitlab/bitbucket and the shared
Gitea/Forgejo platform, `fetchJSONFile` for the github/gitlab presets and the
shared Gitea/Forgejo preset source, and `getReleaseNotesMd` for the bitbucket
changelog source and the shared Gitea/Forgejo changelog source.
`getRepoContents` is gone from `gitea-helper.ts`, the contents schemas move out
of `platform/gitea/schema.ts`, and the Gitea and Forgejo preset sources build
their own `Http` instance instead of importing the platform's.

Behaviour changes:

- GitLab presets no longer look up the project's default branch before
  fetching; they request `?ref=HEAD` like the platform already does, and they
  use the JSON contents endpoint instead of `/raw`. This removes one HTTP
  request per preset lookup.
- A GitHub contents response without a `content` field now surfaces as
  `PRESET_DEP_NOT_FOUND` instead of an uncaught `TypeError`, because the
  base64 decode moved inside the try block.
- GitLab `getRawFile` escapes the file name with `encodeURIComponent` instead
  of only escaping `/`.
- Gitea/Forgejo contents URLs escape each path segment on its own, so a nested
  path keeps its slashes: the platform `getRawFile` and the preset source now
  request `contents/path/custom.json` where they used to request
  `contents/path%2Fcustom.json`. Both spellings work; the unescaped one is the
  documented form and the one the changelog source already used.
- The Gitea/Forgejo changelog source now escapes the segments of the source
  directory and of the changelog file path, as the platform and preset callers
  already did.
- The `Preset URL` trace log in the GitHub and GitLab presets is gone; the URL
  is built inside the util helper.

Not covered here: Bitbucket Server (platform reads `browse`, changelog reads
`raw` - genuinely different endpoints) and the GitHub/GitLab changelog sources,
which use the git tree/blob APIs rather than a path lookup.

* refactor(platform): keep the repo-file helpers in the platform folders

The helpers landed under `lib/util/<host>/`, which added a second home for
host API code next to the platform modules that already own it. Move them
into the platform folder of their host instead, so there is one place per
host rather than two:

- `lib/util/github/contents.ts`  -> `lib/modules/platform/github/contents.ts`
- `lib/util/gitlab/files.ts`     -> `lib/modules/platform/gitlab/files.ts`
- `lib/util/bitbucket/files.ts`  -> `lib/modules/platform/bitbucket/files.ts`
- `lib/util/gitea/contents.ts`   -> `lib/modules/platform/gitea/contents.ts`

The preset and changelog layers import them from there, which is the
direction they already had: the preset sources read `gitea-helper.ts` and the
changelog sources read `platform/*/schema.ts`.

`RepoContents` and `ContentsListResponse` go back to `platform/gitea/schema.ts`
with their tests, because `renovate/zod-schema-location` keeps zod schemas
under `lib/modules/**` in a `schema.ts`. That is also where the changelog
sources read them from today.

The functions keep taking the caller's `Http` instance, so the host type and
its host rules still belong to the calling layer; only the file location
changes.

* refactor(presets): keep using the platform's Gitea and Forgejo clients

The preset sources were switched to `new GiteaHttp()` / `new ForgejoHttp()` to
keep `lib/config/presets` from importing `lib/modules/platform`. That boundary
is gone now that the contents helpers live in the platform folder, and the
second instance never bought anything: `giteaHttp` and `forgejoHttp` are
themselves plain `new GiteaHttp()` / `new ForgejoHttp()`, an `HttpBase` holds
only its host type and its merged default options, and `baseUrl` is module
state shared by every instance of the class rather than per-instance.

Both files are back to what they were, so the preset sources no longer appear
in this change at all.

* refactor(platform): resolve repo-file URLs against the client base url

`getRepoFile()` and `listRepoDir()` took an `apiBaseUrl` positional argument
that meant three different things depending on the caller: an empty string or
a slash for "use the client's own base", a path prefix for Gitea, and a full
API base URL for the preset and changelog layers.

`Http` already owns this: `resolveUrl()` reads `options.baseUrl ?? this.baseUrl`.
The helpers now build a URL relative to the API root and take no base of their
own, so callers reading the host their client is configured for pass nothing,
and callers reading a foreign host pass `baseUrl` in the options they already
pass.

The GitHub, GitLab and Bitbucket platform clients are based at the API root,
so those three call sites lose their placeholder argument outright. The Gitea
client is based at the web root and the rest of that folder prefixes every URL
with `API_PATH`, so the Gitea callers pass that same constant instead of the
duplicate `API_BASE_PATH` this stack had added next to it.

* test(platform): cover the client base url fallback for repo files

The GitHub and GitLab `getRepoFile()` specs always passed a `baseUrl` option,
so the fallback to the client's own base url - the path the platform callers
take now that they pass no base at all - was never exercised. Both specs get a
case that sets a self-hosted base url on the client and reads a file without
passing one, which also pins that a configured endpoint reaches the request.

The Bitbucket and Gitea specs already covered it.

* refactor(platform): name the repo-file helper files.ts on every platform

The helper was named after each vendor's own word for the endpoint:
GitHub and Gitea call it "contents", GitLab calls it "files" and
Bitbucket calls it "src", so the same helper sat under two different
names and neither matched Bitbucket.

Use files.ts everywhere, so a reader looking for "read a file from a
repo" finds the same filename in every platform folder. The vendor's
noun still appears where it belongs: in the request paths, the doc links
and the Gitea schema names.
2026-09-21 15:27:50 +00:00
..

GitLab

Easiest way to run Renovate

For users on GitLab.com, the easiest way to get started is to install the Mend-hosted Renovate app by following these instructions when logging into the Mend Developer Platform. When you use the app, Mend will:

  • authenticate Renovate to GitLab.com
  • keep the tokens safe
  • maintain and update the Renovate version used

If you self-host Renovate you must do the things listed above yourself. Self-hosting is meant for users with advanced use cases, or who want to be in full control of the bot and the environment it runs in. We recommend most users install the Mend-hosted app.

Read the GitLab security page to learn about the security model for both the Mend-hosted app and self-hosted deployments.

After you installed the hosted app, please read the reading list to learn how to use and configure Renovate.

Authentication

You can authenticate Renovate to GitLab, with one of these methods:

Three ways to authenticate, choose one

To start, create either:

  • a Personal Access Token for the Renovate account
  • or a Project Access Token if Renovate only needs to check and update one project. We do not recommend Project Access Tokens, as you need to configure Renovate, and the token, for each project
  • or a Group Access Token to the group Renovate will be working on

Renovate account or token must have at least developer role

The Renovate account, or token, must have at least the Developer role. The developer role allows Renovate to create issues and merge requests.

If you want Renovate to automerge, give appropriate permissions

If you are using automerge, the Renovate account, or token, must have the appropriate "Allowed to merge" permission on the protected branch of your projects.

If only maintainers are allowed to merge, give Maintainer role

If merging is restricted to Maintainers, the Renovate account or token must have the Maintainer role.

Setting up Project Access Tokens or Group Access Tokens

If you are using a project access token, or a group access token, GitLab creates an internal bot user for you. This bot user is the one that will be used to create merge requests and issues.

Use the name and email of this bot user to configure Renovate when verifing users using push rules. For group access tokens, an expiration date is required, unlike project access tokens where it is optional.

To keep using the same GitLab-generated bot account you must rotate/refresh the Group Access Token before the token's expiry date.

We refer to personal access tokens, project access tokens and group access tokens as access tokens in the instructions that follow.

Permissions for access tokens on real runs

For real runs, give the access token these scopes:

  • api

Permissions for access tokens on dry runs

For dry runs, give the access token these scopes:

  • read_api

Letting Renovate use your access token

Let Renovate use your access token by doing one of the following:

  • Set your access token as a token in your config.js file
  • Set your access token as an environment variable RENOVATE_TOKEN
  • Set your access token when you run Renovate in the CLI with --token=

Set platform=gitlab in your Renovate config file

Remember to set platform=gitlab somewhere in your Renovate config file.

Setting up Renovate for a Private Gitlab container registry

If you use a private GitLab container registry, you must:

  • Set the RENOVATE_HOST_RULES CI variable to [{"matchHost": "${CI_REGISTRY}","username": "${GITLAB_USER_NAME}","password": "${RENOVATE_TOKEN}", "hostType": "docker"}].

    Alternatively, if detectHostRulesFromEnv is enabled, you can set the CI variables DOCKER_REGISTRY_GITLAB_COM_USERNAME=${GITLAB_USER_NAME} and DOCKER_REGISTRY_GITLAB_COM_PASSWORD=${RENOVATE_TOKEN}.

  • Make sure the user that owns the access token is a member of the corresponding GitLab projects/groups with the right permissions.

  • Make sure the access token has the read_registry scope.

You may also use a dedicated Deploy Token instead of using RENOVATE_TOKEN as the password in the above host rule example.

Get colored output

You may want to set FORCE_COLOR: 3 to the job, in order to get colored output. GitLab Runner runs the container’s shell in non-interactive mode, so the shell’s TERM environment variable is set to dumb.

Features awaiting implementation

  • The automergeStrategy configuration option has not been implemented for this platform, and all values behave as if the value auto was used. Renovate will accept the Merge Request without further configuration, and respect the strategy defined in the Merge Request, and this cannot be overridden yet

Server version dependent features

We use the GitLab version API to fetch the server version. You can use the experimental feature flag RENOVATE_X_PLATFORM_VERSION to set a specific server version. By setting the server version yourself, you save a API call that fetches the server version.

  • Use Draft: MR prefix instead of WIP: prefix since v13.2.0
  • Do not truncate Markdown body to 25K chars since v13.4.0
  • Allow configure reviewers since v13.9.0
  • Add automerged MRs to merge trains since v17.11.0 (when merge trains are enabled on the project)
  • With platformAutomerge=false, Renovate adds MRs to the merge train itself once all checks have passed, see GitLab Merge Trains

Multiple merge request assignees

Multiple assignees are only available on GitLab Premium and Ultimate tiers. Because of a safeguard in GitLab's API if multiple assignees are set, but not available to the project, only the first assignee will be applied.

Verifying users using push rules

When verifying users using push rules, you must use the name and email of the bot user for gitAuthor.

Repo autodiscover

Renovate can discover repositories on GitLab using the autodiscover feature.

You can change the default server-side sort method and order for autodiscover API. Set those via autodiscoverRepoSort and autodiscoverRepoOrder. Read the GitLab Projects API docs for more details.