Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"enabledManagers": [
"custom.regex"
],
"customManagers": [
{
"customType": "regex",
"fileMatch": [
"^build\\.gradle$"
],
"matchStrings": [
"iceberg_1_[25]_version\\s*=\\s*\"(?<currentValue>[^\"]+)\""
],
"depNameTemplate": "com.linkedin.iceberg:iceberg-core",
"datasourceTemplate": "maven"
}
],
"packageRules": [
{
"matchPackageNames": [
"com.linkedin.iceberg:iceberg-core"
],
"matchCurrentVersion": "/^1\\.2\\./",
"allowedVersions": "/^1\\.2\\./"
},
{
"matchPackageNames": [
"com.linkedin.iceberg:iceberg-core"
],
"matchCurrentVersion": "/^1\\.5\\./",
"allowedVersions": "/^1\\.5\\./"
}
]
}
74 changes: 74 additions & 0 deletions .github/workflows/renovate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Self-hosted Renovate that constantly syncs the linkedin/iceberg fork
# (com.linkedin.iceberg) within its 1.2.x and 1.5.x lines.
#
# Behavior is defined in .github/renovate.json:
# - iceberg_1_2_version (root build.gradle) -> capped to 1.2.x
# - iceberg_1_5_version (root build.gradle) -> capped to 1.5.x
# Only the custom regex manager is enabled, so Renovate touches nothing else.
#
# ── One-time setup ───────────────────────────────────────────────────────────
# Create a repo (or org) secret named RENOVATE_TOKEN so Renovate can open PRs
# AND so CI runs on those PRs (PRs opened with the default GITHUB_TOKEN do NOT
# trigger other workflows). Use either:
# - a classic PAT with `repo` + `workflow` scope, or
# - a fine-grained PAT / GitHub App installation token with read+write on
# Contents and Pull requests.
# If RENOVATE_TOKEN is absent the run falls back to GITHUB_TOKEN: PRs are still
# created, but CI will not auto-run on them.
name: Renovate (linkedin/iceberg sync)

on:
schedule:
# Hourly — "constantly" sync. Renovate is idempotent: a run is a no-op when
# the pinned versions are already the newest within their line.
- cron: '0 * * * *'
workflow_dispatch:
inputs:
logLevel:
description: Renovate log level
required: false
default: info
type: choice
options:
- info
- debug
dryRun:
description: Dry run (extract & log only, open no PRs)
required: false
default: false
type: boolean

# When a dedicated RENOVATE_TOKEN is set, Renovate uses it and these job-token
# permissions are unused. They exist so the GITHUB_TOKEN fallback can still
# create branches and PRs (CI just won't auto-run on those PRs).
permissions:
contents: write
pull-requests: write

concurrency:
group: renovate
cancel-in-progress: false

jobs:
renovate:
name: Renovate
runs-on: ubuntu-latest
steps:
# Set RENOVATE_DRY_RUN only when explicitly requested; leaving it unset on
# scheduled runs avoids a config-validation warning for an invalid value.
- name: Enable dry run
if: ${{ inputs.dryRun }}
run: echo "RENOVATE_DRY_RUN=full" >> "$GITHUB_ENV"

- name: Run Renovate
# renovatebot/github-action publishes only full vX.Y.Z tags (no moving
# major tag); the github-actions Dependabot updater keeps this current.
uses: renovatebot/github-action@v46.1.15
with:
token: ${{ secrets.RENOVATE_TOKEN || secrets.GITHUB_TOKEN }}
env:
# Only operate on this repository; do not crawl the whole org.
RENOVATE_REPOSITORIES: ${{ github.repository }}
RENOVATE_AUTODISCOVER: 'false'
# Per-repo config lives in .github/renovate.json (auto-detected).
LOG_LEVEL: ${{ inputs.logLevel || 'info' }}
70 changes: 70 additions & 0 deletions docs/development/renovate-iceberg-sync.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Renovate: linkedin/iceberg version sync

OpenHouse depends on the LinkedIn Iceberg fork (`com.linkedin.iceberg`, published
to Maven Central) and deliberately pins **two minor lines at once**:

| Source of truth | Line | Drives |
| --- | --- | --- |
| `iceberg_1_2_version` in `build.gradle` | `1.2.x` | Spark 3.1 stack, `iceberg-1.2` integrations, `datalayout` |
| `iceberg_1_5_version` in `build.gradle` | `1.5.x` | Spark 3.5 stack, `iceberg-1.5` integrations, services |

Renovate ([`.github/renovate.json`](../../.github/renovate.json)) keeps each pin at
the newest release **within its own line** and opens a PR per line when a newer
version exists. It runs hourly via the self-hosted
[`renovate.yml`](../../.github/workflows/renovate.yml) workflow.

## Why Renovate (and not native Dependabot)

Native Dependabot cannot express this repo's setup:

1. **Two minor lines of the same artifacts.** `iceberg-core`, `iceberg-common`,
`iceberg-data`, and `iceberg-bundled-guava` are each pinned at both `1.2.x`
and `1.5.x`. Dependabot's `ignore` rules are keyed per-artifact, so it would
try to converge both pins onto a single latest version, breaking one line.
Renovate's `matchCurrentVersion` evaluates each occurrence against its own
current value, so the `1.2.0.x` pin and the `1.5.2.x` pin get independent
ceilings.
2. **Cross-file `ext` indirection.** Versions are defined once in the root
`build.gradle` and read elsewhere via `rootProject.ext.…` and `buildSrc`
convention plugins. Instead of relying on a parser to follow that chain, a
Renovate `customManager` (regex) updates the source-of-truth lines directly.

`enabledManagers: ["custom.regex"]` scopes Renovate to **only** these three
version strings — it does not touch any other dependency. GitHub Actions updates
remain handled by the existing [`dependabot.yml`](../../.github/dependabot.yml).

## How the line caps work

Each line is held by a `packageRule` keyed on the current version, e.g. for the
1.5 line:

```json
{
"matchPackageNames": ["com.linkedin.iceberg:iceberg-core"],
"matchCurrentVersion": "/^1\\.5\\./",
"allowedVersions": "/^1\\.5\\./"
}
```

The 4-part LinkedIn versions (`1.5.2.11`) are compared with Renovate's `maven`
versioning, and release candidates (`1.5.2.0-rc1`) are skipped as unstable.

## One-time setup

Create a repository (or org) secret named **`RENOVATE_TOKEN`** so Renovate can
open PRs **and** so CI runs on them — PRs opened with the default `GITHUB_TOKEN`
do not trigger other workflows. Use one of:

- a classic PAT with `repo` + `workflow` scope, or
- a fine-grained PAT / GitHub App installation token with read+write on
**Contents** and **Pull requests**.

Without `RENOVATE_TOKEN` the workflow falls back to `GITHUB_TOKEN`: PRs are still
created, but their CI must be re-run manually.

## Verifying / running on demand

- Trigger **Actions → "Renovate (linkedin/iceberg sync)" → Run workflow** with
the `Dry run` option to see what Renovate would do without opening PRs.
- Validate config changes locally:
`npx --yes --package renovate -- renovate-config-validator .github/renovate.json`