Files
renovate/lib/modules/platform/github
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
..

GitHub and GitHub Enterprise Server

Most of the information on this page is meant for users who want to self-host Renovate on GitHub or GitHub Enterprise Server.

Easiest way to run Renovate

For users on GitHub Cloud (github.com), the easiest way to get started is to install the Mend Renovate app from the GitHub marketplace. When you use the app, Mend will:

  • authenticate the Renovate app to GitHub
  • 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 Renovate and the environment it runs in. We recommend most users install the Mend Renovate app.

Read the Security and Permissions page to learn about the Security and Permissions needed for the Mend Renovate app.

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

Authentication

First, create a fine-grained or a classic PAT. The PAT must have the repo scope. If you want Renovate to also update your GitHub Action files, you must grant the workflow scope.

Read the GitHub Docs, about Personal Access Tokens to learn more about PATs.

Let Renovate use your PAT by doing one of the following:

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

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

If you use GitHub Enterprise Server then endpoint must point to https://github-enterprise.example.com/api/v3/. You can choose where you want to set endpoint:

  • In your config.js file
  • In a environment variable
  • In a CLI parameter

!!! tip "Labels and forking mode" If you're self-hosting Renovate on GitHub.com with GitHub Actions in forking mode, and want Renovate to apply labels then you must give the PAT triage level rights on issues. The triage level allows the PAT to apply/dismiss existing labels.

Running using a fine-grained token

Permissions

A fine-grained token must have these permissions:

Permission Access Level
Members Read-only Organization
Commit statuses Read and write Repository or Organization
Contents Read and write Repository or Organization
Dependabot alerts Read-only Repository or Organization
Issues Read and write Repository or Organization
Pull requests Read and write Repository or Organization
Workflows Read and write Repository or Organization

!!! tip "Use a dedicated role account" Consider creating a GitHub App to use instead of using your own GitHub user account.

Running as a GitHub App

Instead of a dedicated account with a Personal Access Token you can run renovate as a self-hosted GitHub App.

When creating the GitHub App give it the following permissions:

Permission Scope
Checks read + write
Commit statuses read + write
Contents read + write
Issues read + write
Pull requests read + write
Workflows read + write
Administration read
Dependabot alerts read
Members read
Metadata read

Other values like Homepage URL, User authorization callback URL and webhooks can be disabled or filled with dummy values.

Inside your config.js you need to set the following values, assuming the name of your app is self-hosted-renovate:

token:"ghs_123exampletoken"

You must use a GitHub App Installation token.

Previously, the token had to be prefixed with x-access-token:. We recommend you replace any prefixed tokens with normal tokens. We will drop support for prefixed tokens in the future.

Any tokens that do not start with ghs_ (for example tokens from GitHub Enterprise Server versions before version 3.2) must be prefixed with x-access-token:.

!!! note The installation tokens expire after 1 hour and need to be regenerated regularly. Alternatively as environment variable RENOVATE_TOKEN, or via CLI --token=.

!!! tip "Third-party tools to regenerate installation tokens" If you're self-hosting Renovate within a GitHub Actions workflow, then you can use the actions/create-github-app-token action. If you use Node.js/CLI, then you can use the github-app-installation-token package. If you use Docker, then you can use the mshekow/github-app-installation-token image.

repositories: ["orgname/repo-1","orgname/repo-2"]

List of repositories to run on. Alternatively as comma-separated environment variable RENOVATE_REPOSITORIES. The GitHub App installation token is scoped at most to a single organization and running on multiple organizations requires multiple invocations of renovate with different token and repositories parameters.

username:"self-hosted-renovate[bot]" (optional, autodetected if not supplied)

The slug name of your app with [bot] appended

gitAuthor:"Self-hosted Renovate <123456+self-hosted-renovate[bot]@users.noreply.github.enterprise.com>" (optional, autodetected if not supplied)

The GitHub App associated email to match commits to Renovate. It needs to have the user id and the username followed by the users.noreply.-domain of either github.com or the GitHub Enterprise Server. A way to get the user id of a GitHub app is to query the user API at api.github.com/users/self-hosted-renovate[bot] (github.com) or github.enterprise.com/api/v3/users/self-hosted-renovate[bot] (GitHub Enterprise Server).

Package Registry Credentials

When Renovate runs against repositories on github.com, and the environment variable RENOVATE_X_GITHUB_HOST_RULES is set, then Renovate automatically provisions hostRules for these GitHub Packages registries using the platform token:

  • ghcr.io
  • maven.pkg.github.com
  • npm.pkg.github.com
  • nuget.pkg.github.com
  • rubygems.pkg.github.com

!!! warning We reverted the Package Registry Credentials feature to experimental mode, because users reported it's not working correctly with app tokens.