Renovate

How Renovate maintains CKI dependencies

Renovate automates dependency updates across CKI repositories – container base image digests, RPM lockfiles, Python lockfiles, and CI image references.

Shared presets

Two presets live in cki-lib/.gitlab/renovate/:

  • default.json: Base configuration for repos that want fine-grained per-dependency MRs with individual automerge decisions.
  • weekly-grouped.json: Extends default but batches ALL dependency changes into a single Sunday MR with automerge – used by repos where frequent individual MRs would be noisy (kernel-qe-tools, kernel-tests, kpet-db, qe-pipeline-definition, test-plans, gitlab-ci-templates, beaker-jobwatch, containers).

Every CKI repo extends one preset via renovate.json:

{
  "extends": ["local>cki-project/cki-lib//.gitlab/renovate/default"]
}

Repos on a different GitLab instance (e.g., deployment-all on gitlab.cee.redhat.com) use "gitlab>cki-project/cki-lib//..." instead of "local>".

Managers

Three manager types are enabled:

  • pip-compile: Maintains Python lockfiles by reading the uv pip compile command from requirements.lock headers and re-executing it.
  • rpm-lockfile: RPM lockfile maintenance (automerges).
  • custom.regex: One manager with 4 match patterns:
    • Containerfile.in base image digests
    • CI image digests in .gitlab-ci.yml and .gitlab/ci_templates/ci-images.yml
    • ARG versions in Containerfiles
    • rpms.in.yaml base images

Automerge and scheduling

RPM lockfile maintenance and CI image digest updates (ci-images group) automerge. Python dependency updates do not automerge (they get minimumReleaseAge: "7 days").

platformAutomerge: false – automerge is handled by Renovate itself (via GitLab merge API after approval), NOT by GitLab’s native auto-merge feature. This distinction matters because Renovate controls the timing and conditions.

automergeSchedule: "* 8-16 * * 1-4" restricts automerges to weekday working hours (Mon-Thu, 8:00-16:00 UTC) so automated changes only land during business hours.

Branch naming

Per-image additionalBranchPrefix prevents branch collisions, resulting in branches like renovate/pipeline-herder/lockfile-maintenance or renovate/pipeline-herder/quay.io-fedora-fedora-44.

Auto-approval flow

  1. Renovate files MR on renovate/* branch
  2. CI passes
  3. Pipeline webhook fires
  4. mr-auto-approver approves the MR
  5. Renovate merges via GitLab API

Currently configured for ~25 projects across cki-project and redhat/centos-stream/tests/kernel groups.

Cooldown

7-day minimumReleaseAge for language ecosystem deps (Python, JS, Rust, Go, Java, Ruby, PHP, .NET – via matchCategories in default.json); --exclude-newer=P7D in lockfile generation. These are complementary: minimumReleaseAge delays the MR, --exclude-newer prevents the lockfile from including packages released in the last 7 days.

Docker and RPM updates have no release age gate.

Per-package cooldown override: --exclude-newer-package=<pkg>=false exempts a specific package from the 7-day cooldown (configured in the lockfile header).

Fedora version cap

allowedVersions: "<= 44" (in cki-lib/.gitlab/renovate/default.json) prevents premature Fedora upgrades. Must be manually bumped when a new Fedora release is validated.

Post-upgrade automation

  • rpm-lockfile-prototype rpms.in.yaml runs after base image bumps in rpms.in.yaml (configured in default.json postUpgradeTasks).
  • post-upgrade.sh (mounted via ConfigMap from deployment-all) regenerates pipeline/requirements-lock.yml in pipeline-definition.

CI validation

Two scripts enforce Renovate regex compatibility in CI:

  • cki_validate_lockfiles.sh: Lockfile header format (= separators, --exclude-newer=, --no-strip-extras). See Lockfiles for header rules.
  • cki_validate_containerfiles.sh: Digest pins in Containerfile.in and rpms.in.yaml.

Both scripts live in cki-lib/shell-scripts/ and are distributed via pip install into the cki-tools image.

The uv wrapper

The dependency-tools image ships a uv wrapper at /usr/local/bin/uv that transparently handles two Renovate pip-compile gaps:

  1. Two-pass --override for VCS deps: Pass 1 discovers VCS dep extras via PyPI-only constraints; pass 2 resolves with a targeted --override containing correct extras + pinned SHAs (astral-sh/uv#11247).
  2. Forced --upgrade for range constraint updates: Ensures lockfiles actually pick up new versions when constraints widen.

The wrapper records the clean (unwrapped) command in the lockfile header via --custom-compile-command.