Skip to content

Dependency management

Codebahn does not have a built-in Dependabot. If you are coming from GitHub, your .github/dependabot.yml file is ignored.

The standard alternative is Renovate. It runs as a scheduled CI workflow on Codebahn’s runners, scans your repo for outdated dependencies, and opens pull requests with the updates. This guide walks through the setup.

Codebahn provides a built-in bot account (@codebahn-bot) for automated dependency updates. Add it as a collaborator on your repository and Codebahn handles the rest: a short-lived, repo-scoped token is generated for each CI run and injected as CODEBAHN_BOT_TOKEN. No manual token creation or secret management.

  1. Open your repository on Codebahn
  2. Go to Settings > Collaborators
  3. Search for codebahn-bot and add it with Write access

Pull requests from Renovate will appear as authored by @codebahn-bot. CI runs on those PRs automatically.

Create .codebahn/workflows/renovate.yml:

name: Renovate
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
jobs:
renovate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: renovatebot/github-action@v46.1.17
with:
token: ${{ secrets.CODEBAHN_BOT_TOKEN }}
env:
RENOVATE_PLATFORM: forgejo
RENOVATE_ENDPOINT: https://codebahn.net/api/v1
RENOVATE_REPOSITORIES: ${{ github.repository }}
LOG_LEVEL: info

What each piece does:

  • cron: '0 6 * * *' runs Renovate daily at 06:00 UTC. This controls how often Renovate checks for updates. When it creates PRs is a separate setting (see scheduling).
  • workflow_dispatch lets you trigger a run manually from the Actions tab.
  • RENOVATE_PLATFORM: forgejo tells Renovate it is talking to a Forgejo instance. Do not use gitea.
  • RENOVATE_ENDPOINT must include /api/v1.
  • RENOVATE_REPOSITORIES tells Renovate which repo to scan. On GitHub this is auto-detected; on Forgejo you must set it explicitly. ${{ github.repository }} resolves to owner/repo.
  • LOG_LEVEL: info keeps output readable. Use debug during initial setup if something is not working.

The action resolves from GitHub automatically. ubuntu-latest routes to Codebahn’s hosted runners. No special configuration needed.

Create renovate.json in your repository root:

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"major": {
"enabled": false
}
}

config:recommended enables the dependency dashboard (an issue Renovate maintains with the status of all updates), semantic commit prefixes, and monorepo-aware grouping. major is disabled because major version bumps often have breaking changes and should be done by hand after reading the changelog. Renovate still creates PRs for minor and patch updates.

A more opinionated config that also auto-merges patch and minor updates:

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:best-practices"],
"major": {
"enabled": false
},
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true
}
]
}

Push both files and trigger a run from the Actions tab, or wait for the next cron schedule. Renovate scans your repo and opens its first pull requests. The CODEBAHN_BOT_TOKEN secret is injected automatically; you do not need to create it.

Renovate auto-detects all package managers. You do not list ecosystems. Instead, you use packageRules to customize behavior per manager.

Dependabot Renovate
package-ecosystem: "npm" Auto-detected. Scope with "matchManagers": ["npm"] in packageRules
package-ecosystem: "github-actions" Auto-detected. Manager name: "github-actions"
package-ecosystem: "docker" Auto-detected. Renovate splits Docker into "dockerfile", "docker-compose", and others. Use "matchManagers": ["dockerfile"] to scope to Dockerfiles only
package-ecosystem: "gomod" Auto-detected. Manager name: "gomod"
schedule.interval: "daily" "schedule": ["before 5am"]
schedule.interval: "weekly" "schedule": ["before 5am on Monday"]
schedule.interval: "monthly" "schedule": ["before 5am on the first day of the month"]
directory: "/" Auto-scanned. Scope with "matchFileNames" in packageRules
open-pull-requests-limit: 10 "prConcurrentLimit": 10
labels: ["dependencies"] "labels": ["dependencies"]
reviewers: ["user1"] "reviewers": ["user1"]
groups.name.patterns "matchPackageNames" with regex (e.g. "/^@types/") + "groupName" in packageRules
ignore with update-types "matchPackageNames" + "matchUpdateTypes" + "enabled": false in packageRules
versioning-strategy: increase "rangeStrategy": "bump"
versioning-strategy: lockfile-only "rangeStrategy": "update-lockfile"

Renovate uses a natural-language schedule syntax, not cron. The schedule in renovate.json controls when PRs are created, separate from the workflow cron that controls when Renovate checks.

Before (.github/dependabot.yml):

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
groups:
types-packages:
patterns:
- "@types/*"
ignore:
- dependency-name: "react"
update-types: ["version-update:semver-major"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "ci"

After (renovate.json):

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"schedule": ["before 5am on Monday"],
"prConcurrentLimit": 10,
"labels": ["dependencies"],
"packageRules": [
{
"matchManagers": ["npm"],
"matchPackageNames": ["/^@types/"],
"groupName": "type definitions"
},
{
"matchManagers": ["npm"],
"matchPackageNames": ["react"],
"matchUpdateTypes": ["major"],
"enabled": false
},
{
"matchManagers": ["github-actions"],
"labels": ["ci"],
"pinDigests": true
}
]
}

The npm and GitHub Actions ecosystems are auto-detected. packageRules entries scope behavior to each manager. The @types/* group and the React major ignore carry over directly.

Delete .github/dependabot.yml after you confirm Renovate is working. Keeping both creates duplicate PRs.

Two layers control timing:

  1. Workflow cron (.codebahn/workflows/renovate.yml): how often Renovate runs and checks for updates. Default in the example above: once a week (Monday at 06:00 UTC).
  2. Renovate schedule (renovate.json): when Renovate is allowed to create pull requests. If the schedule window is closed, Renovate still runs but holds new PRs until the window opens.

If you only want updates on Monday mornings:

{
"schedule": ["before 9am on Monday"],
"timezone": "Europe/Stockholm"
}

Without a schedule key, Renovate creates PRs whenever it finds updates, on every cron run.

Most open-source dependencies live on GitHub. When Renovate fetches changelogs and release notes for PRs, it hits the GitHub API. Without authentication, GitHub rate-limits these requests and PR descriptions may be missing release notes.

Add a GitHub personal access token (read-only, no scopes needed for public repos) as a secret:

  1. On GitHub: Settings > Developer settings > Personal access tokens > Fine-grained tokens
  2. Generate a token with no repository access (public data only)
  3. On Codebahn: add it as a repository secret named GH_COM_TOKEN

Forgejo blocks secret names starting with GITHUB_, so the secret is named GH_COM_TOKEN. Map it to the env var Renovate expects in the workflow:

env:
RENOVATE_PLATFORM: forgejo
RENOVATE_ENDPOINT: https://codebahn.net/api/v1
GITHUB_COM_TOKEN: ${{ secrets.GH_COM_TOKEN }}
LOG_LEVEL: info

The env var Renovate reads is GITHUB_COM_TOKEN, not RENOVATE_GITHUB_COM_TOKEN. The secret name (GH_COM_TOKEN) can be anything that Forgejo allows.

The setup above is per-repo: each repository gets its own workflow file and renovate.json, and @codebahn-bot is added as a collaborator on each one. The CODEBAHN_BOT_TOKEN is scoped to whichever repo the workflow runs in, so each repo is isolated.

For a team with many repos, Renovate also supports autodiscover mode: a single workflow in one “renovate-config” repo scans every repo the bot can access. Set RENOVATE_AUTODISCOVER: 'true' in the workflow env and use autodiscoverFilter to limit which repos are scanned. See the Renovate documentation on autodiscovery for the details.