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.
Enable the dependency bot
Section titled “Enable the dependency bot”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.
- Open your repository on Codebahn
- Go to Settings > Collaborators
- Search for
codebahn-botand add it with Write access
Pull requests from Renovate will appear as authored by @codebahn-bot. CI runs on those PRs automatically.
Add the workflow
Section titled “Add the workflow”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: infoWhat 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_dispatchlets you trigger a run manually from the Actions tab.RENOVATE_PLATFORM: forgejotells Renovate it is talking to a Forgejo instance. Do not usegitea.RENOVATE_ENDPOINTmust include/api/v1.RENOVATE_REPOSITORIEStells Renovate which repo to scan. On GitHub this is auto-detected; on Forgejo you must set it explicitly.${{ github.repository }}resolves toowner/repo.LOG_LEVEL: infokeeps output readable. Usedebugduring 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.
Add a Renovate config
Section titled “Add a Renovate config”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.
Migrating from Dependabot
Section titled “Migrating from Dependabot”Renovate auto-detects all package managers. You do not list ecosystems. Instead, you use packageRules to customize behavior per manager.
Field mapping
Section titled “Field mapping”| 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.
Worked example
Section titled “Worked example”Before (.github/dependabot.yml):
version: 2updates: - 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.
Scheduling
Section titled “Scheduling”Two layers control timing:
- 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). - 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.
Optional: GitHub token for changelogs
Section titled “Optional: GitHub token for changelogs”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:
- On GitHub: Settings > Developer settings > Personal access tokens > Fine-grained tokens
- Generate a token with no repository access (public data only)
- 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: infoThe 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.
Multiple repos
Section titled “Multiple repos”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.

