{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended", ":dependencyDashboard", ":semanticCommits", ":enableVulnerabilityAlerts", ":rebaseStalePrs", "customManagers:biomeVersions" ], "timezone": "America/New_York", "minimumReleaseAge": "7 days", "prCreation": "immediate", "prConcurrentLimit": 3, "prHourlyLimit": 5, "rebaseWhen": "behind-base-branch", "commitMessagePrefix": "chore(deps):", "commitMessageAction": "update", "commitMessageExtra": "to {{newVersion}}", "commitMessageTopic": "{{depName}}", "prBodyTemplate": "{{{header}}}{{{table}}}{{{notes}}}{{{changelogs}}}{{{controls}}}{{{footer}}}", "prBodyColumns": ["Package", "Update", "New value", "References"], "prBodyDefinitions": { "Package": "{{{depNameLinked}}}", "Update": "{{{updateType}}}", "New value": "`{{{newVersion}}}`", "References": "{{{references}}}" }, "prFooter": "---\n\n🤖 This PR was generated by Renovate Bot", "automergeType": "pr", "automergeStrategy": "squash", "platformAutomerge": false, "ignoreTests": false, "configMigration": true, "rollbackPrs": true, "osvVulnerabilityAlerts": true, "packageRules": [ { "matchUpdateTypes": ["minor", "patch"], "groupName": "all non-major dependencies", "groupSlug": "minor-patch", "schedule": ["every 2 weeks on monday"], "labels": ["dependencies", "automerge"], "automerge": true }, { "description": "Majors auto-merge, but only behind the full CI gate and a 14-day soak. `ignoreTests` is false, so Renovate merges only once the branch's status checks are green; a major whose CI fails simply stays open, labelled and assigned, and that failure is the human-review hook. `assignAutomerge` is required for that visibility: it defaults to false, which makes Renovate suppress assignees on any PR it intends to automerge and apply them only once checks have failed, so without it the assignment above would silently never happen. Note the corollary of the CI gate: in a repo with no CI checks at all there is nothing to gate on and the major merges unreviewed, so a repo that needs review must have a check that can fail.", "matchUpdateTypes": ["major"], "groupName": "all major dependencies", "groupSlug": "major", "schedule": ["every 4 weeks on tuesday"], "automerge": true, "labels": ["dependencies", "major", "breaking-change"], "assignees": ["peculiar-cloud-git"], "assignAutomerge": true, "prPriority": 10, "minimumReleaseAge": "14 days" }, { "matchDatasources": ["docker"], "pinDigests": true }, { "matchManagers": ["github-actions"], "pinDigests": true }, { "description": "Chainguard images are continuously rebuilt on rolling tags (latest, latest-dev) for CVE patching, and the free tier publishes no version tags. Pinning their digest fights that model: the tag moves faster than the release-age gate, so Renovate force-pushes a fresh digest to the open branch every run and the PR never merges, while the pin holds the base at a stale, unpatched build. Track the rolling tag instead. Must come after the matchDatasources:[docker] rule above, which sets pinDigests:true.", "matchDatasources": ["docker"], "matchPackageNames": ["/^cgr\\.dev\\/chainguard\\//"], "pinDigests": false }, { "description": "A rolling Chainguard tag has no meaningful digest update to raise: the digest changes on every upstream rebuild, so each one would be a fresh PR for a base image the build already picks up automatically.", "matchDatasources": ["docker"], "matchPackageNames": ["/^cgr\\.dev\\/chainguard\\//"], "matchUpdateTypes": ["digest"], "enabled": false }, { "description": "Images under ghcr.io/peculiar-cloud are this org's own CI build outputs on `latest` tags, deployed by watchtower, not third-party dependencies. Renovate has nothing useful to say about them: it cannot read them without registry credentials (producing 'No docker auth found - returning'), and authenticating would only enrol a self-published rolling tag in the same digest churn as the Chainguard rule above. pinDigests is disabled alongside so no @sha256 suffix is left stranded and unrefreshed once the dependency is off.", "matchDatasources": ["docker"], "matchPackageNames": ["/^ghcr\\.io\\/peculiar-cloud\\//"], "enabled": false, "pinDigests": false }, { "description": "Exempt pin, pinDigest and digest updates from the release-age gate. A pin adopts nothing new: it records the version already resolved and running. A digest refresh follows a tag that is already pinned and trusted (e.g. actions/checkout@v6), so it needs no supply-chain soak. Critically, a moving tag's digest can never age in at all, because each upstream move resets the clock, so without this the digest PR would sit open forever and rebase on every push to the default branch.", "matchUpdateTypes": ["pin", "pinDigest", "digest"], "minimumReleaseAge": "0 days" }, { "description": "Digest and SHA pins are mechanical and low-risk, so automerge them behind CI: this clears the one-time pinDigests wave and stops ongoing digest updates piling up as open PRs.", "matchUpdateTypes": ["pin", "pinDigest", "digest"], "automerge": true, "labels": ["dependencies", "pin", "automerge"] }, { "description": "Batch recurring digest refreshes into one self-merging PR on the biweekly cadence. A pinned action's major tag (e.g. actions/checkout@v6) moves whenever upstream ships a patch, and unbatched each move raises a separate digest PR that rebases and re-runs CI on every push until it merges. The one-time pin/pinDigest wave stays immediate; only recurring refreshes are scheduled.", "matchUpdateTypes": ["digest"], "groupName": "digest refreshes", "groupSlug": "digest-refreshes", "schedule": ["every 2 weeks on monday"] }, { "matchDepTypes": ["devDependencies"], "matchUpdateTypes": ["major"], "automerge": true, "labels": ["dependencies", "dev", "automerge"] }, { "description": "Suppress the Playwright image as a docker dependency. The built-in github-actions manager also extracts a `container:`/`services:` image with the docker datasource, so without this the same tag becomes two dependencies: the npm-backed one from the customManager, and a plain docker one that could bump the image alone and reintroduce the browser-version mismatch the customManager exists to prevent. pinDigests is disabled here too, because a @sha256 suffix left attached would never be refreshed once the dependency is disabled, letting the visible tag move while Docker kept selecting the old image. THIS RULE MUST STAY LAST. Renovate merges matching packageRules in declaration order, so the earlier matchDatasources:[docker] and matchManagers:[github-actions] rules both set pinDigests:true and would override it from any earlier position. The image must never carry a digest.", "matchDatasources": ["docker"], "matchPackageNames": ["mcr.microsoft.com/playwright"], "enabled": false, "pinDigests": false }, { "description": "Keep the tldraw SDK packages on one version. They are released in lockstep and mixing versions breaks the sync protocol, so they are split out of the shared minor/patch group and bumped together. Declared after the shared group rules so it overrides their groupName for these packages.", "matchPackageNames": ["tldraw", "@tldraw/assets", "@tldraw/sync", "@tldraw/sync-core"], "matchUpdateTypes": ["patch", "minor", "major"], "groupName": "tldraw sdk", "groupSlug": "tldraw-sdk", "automerge": true, "labels": ["dependencies", "tldraw", "automerge"] }, { "description": "Keep TypeScript within the range supported by typescript-eslint.", "matchPackageNames": ["typescript"], "allowedVersions": "<6.1.0" } ], "lockFileMaintenance": { "description": "Lockfile maintenance has no release timestamp. Allow missing timestamps until renovatebot/renovate#45236 is fixed; CI still gates merging.", "minimumReleaseAgeBehaviour": "timestamp-optional", "enabled": true, "schedule": ["every 4 weeks on wednesday"], "commitMessageAction": "refresh", "automerge": true, "labels": ["dependencies", "lock-file"] }, "vulnerabilityAlerts": { "enabled": true, "labels": ["security", "urgent"], "reviewers": ["peculiar-cloud-git"], "minimumReleaseAge": "0 days", "schedule": ["at any time"], "automerge": true }, "postUpdateOptions": ["gomodTidy", "npmDedupe"], "rangeStrategy": "bump", "separateMajorMinor": true, "separateMinorPatch": false, "customManagers": [ { "customType": "regex", "description": "Read the Playwright CI container image tag (mcr.microsoft.com/playwright:vX.Y.Z-noble in workflow files) as the @playwright/test npm version. Tying the image and the package to one dependency and datasource guarantees they bump together to the identical version (grouped as 'playwright'); managing the image as a standalone docker tag lets it lag the package and break the browser launch at runtime.", "managerFilePatterns": ["/^\\.github/workflows/.+\\.ya?ml$/"], "matchStrings": [ "mcr\\.microsoft\\.com/playwright:v(?\\d+\\.\\d+\\.\\d+)-noble" ], "depNameTemplate": "@playwright/test", "datasourceTemplate": "npm", "versioningTemplate": "npm" } ] }