Prevent Renovate from opening dependency pull requests or merge requests until the proposed repository state passes checks against source-backed compatibility.fyi metadata. The repository provides a GitHub Action and a GitHub-hosted GitLab CI remote template.
The gate is designed for relationships Renovate cannot evaluate by itself, such as:
- whether a CloudNativePG version supports a proposed PostgreSQL operand version;
- whether a Kubernetes operator supports the Kubernetes version being proposed;
- whether a project release supports a proposed Java, database, or platform version.
The gate never queries a live cluster and never executes code from the consumer repository. It reads declared YAML values, calls the public compatibility API, and reports a CI status.
- Renovate discovers an update and creates its branch.
- Renovate's
prCreation: "status-success"setting keeps the pull request or merge request closed while branch checks are pending or failing. - The gate reads its configuration from the repository's default branch.
- It compares the configured project and dependency versions in the default branch with the resulting values in the Renovate branch.
- For every applicable gate, it calls
https://compatibility.fyi/api/v1/check. - It reports
compatibility.fyi/gateas:successwhen every applicable check passes;- a non-blocking warning when an
unknownresult or API error uses thewarnpolicy; failurefor documented incompatibility or evidence below policy;errorfor invalid configuration, or for unknown compatibility and API failures configured with theblockpolicy.
- Renovate opens the pull request or merge request on its next run after the combined branch status becomes green.
On GitHub, the workflow completes successfully after publishing a separate commit status; warnings use a successful status plus a warning annotation and step-summary details. On GitLab, warnings use an allowed-to-fail exit code so the job is orange while the pipeline remains successful. Blocking results still fail the GitLab job. In both cases, a later scheduled evaluation can replace the previous result on the same commit without requiring a new branch commit.
The recommended setup below calls the repository's reusable workflow at the job level:
compatibility-fyi/compatibility-gate/.github/workflows/gate.yml@v1. That wrapper creates the
runner, checks out the caller repository, and invokes the underlying Marketplace action. The direct
action reference is compatibility-fyi/compatibility-gate@v1; use it at the step level when you
need a custom workflow. Both forms run the same compatibility gate.
Create .github/compatibility-fyi.yaml on the default branch:
version: 1
gates:
- id: cnpg-postgresql
project:
id: cloudnativepg
version:
files:
- crds/cloudnative-pg/crds.yaml
document:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata.name: cloudnative-pg
value: spec.ref.tag
dependency:
id: postgresql
versions:
files:
- apps/**/postgres/*.yaml
document:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
value: spec.imageName
extract: ":(?<version>[^@]+)$"
policy:
unknown: block
apiError: block
minimumConfidence: high
maximumEvidenceAgeDays: 180This example reads the CloudNativePG project version from a Flux GitRepository, finds every
CloudNativePG Cluster, extracts PostgreSQL versions from spec.imageName, and checks the complete
state that would exist after merging the branch.
Your project selector must identify the version actually deployed. If a Helm chart version differs
from its application version, use the Helm selector to resolve the chart’s
appVersion, or select an explicit application/image version.
Each gate describes one project-to-dependency relationship. To validate a combination, configure one gate per relationship. The action evaluates every applicable gate against the complete proposed repository state and publishes one combined commit status. Every applicable gate and every selected dependency version must pass.
For example, a CloudNativePG update that must work with both the declared Kubernetes version and
PostgreSQL operand versions uses two gates with the same project selector. Use kubernetes and
postgresql as the separate dependency keys. A grouped Renovate branch is allowed only when both
relationships pass. The action does not need a separate multi-dependency API endpoint for this
behavior.
The API distinguishes four evidence kinds through its basis field:
supported: upstream documents support for the requested combination.tested: upstream tests the combination; this is distinct from a vendor support guarantee.recommended: upstream recommends an alignment, without establishing compatibility.bundled: upstream ships the versions together, without establishing general compatibility.
Matching supported or tested evidence can pass the gate, subject to confidence and age policies.
Recommended and bundled evidence returns unknown even when a range or exact-version constraint
matches. Missing coverage also returns unknown; only explicit upstream incompatibility produces
incompatible. See the API result semantics.
For example, ACM's bundled Multicluster Engine mapping is useful packaging evidence, but cannot
pass the default unknown-blocking policy. An unknown: allow or warn policy is a deliberate
exception, not a compatibility confirmation. Missing project/dependency keys can also mean a matrix
was withdrawn or renamed; inspect the current API catalog before configuring a gate.
Create .github/workflows/compatibility-fyi.yml:
name: compatibility.fyi gate
on:
push:
branches:
- "renovate/**"
schedule:
- cron: "23 */6 * * *"
workflow_dispatch:
jobs:
gate:
permissions:
contents: read
statuses: write
uses: compatibility-fyi/compatibility-gate/.github/workflows/gate.yml@v1
with:
mode: ${{ github.event_name == 'push' && 'current' || 'all' }}Do not add a paths filter. Every Renovate branch needs either a compatibility decision or an
explicit not-applicable success; a branch with no status remains pending.
For maximum supply-chain safety, replace v1 with the full commit SHA of the release. Renovate's
github-actions manager can keep that SHA updated.
The scheduled trigger reevaluates existing Renovate branches when compatibility.fyi metadata changes without a new commit on those branches.
The reusable workflow runs its own action revision using GitHub's self-repository reference, so pinning the workflow also pins the action it executes. This requires GitHub.com and runner 2.336.0 or newer, which GitHub-hosted runners provide. For GitHub Enterprise Server, use the direct action form with a runner that supports Node.js 24 actions.
Apply prCreation: "status-success" globally:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"prCreation": "status-success"
}Or restrict it to selected packages:
{
"packageRules": [
{
"matchPackageNames": ["ghcr.io/cloudnative-pg/postgresql"],
"prCreation": "status-success"
}
]
}Global configuration is simpler and ensures grouped updates are also gated. It delays every Renovate pull request until a later Renovate run sees green branch checks. Unrelated branches receive a successful “not applicable” gate status.
GitLab consumes a public template directly from this GitHub repository with include:remote. It is
not a GitLab CI/CD Catalog component and does not require a mirrored GitLab project. The pinned
include below requires GitLab 17.9 or newer for
include:integrity.
Create .gitlab/compatibility-fyi.yaml on the default branch. The schema is identical to the GitHub
configuration shown above.
Add this to .gitlab-ci.yml:
---
include:
- remote: "https://raw.githubusercontent.com/compatibility-fyi/compatibility-gate/81b179b1bc4d88161603ed9ad1acda6920e9a54a/gitlab/compatibility-gate.yml"
integrity: "sha256-eih2hilPDzg6HGqq0YjCQ5jUXJ1a1CEDwX3Wip/hAz0="The released README contains the exact immutable commit and SHA-256 integrity value. Do not replace
the commit with master: GitLab fetches remote includes without authentication, and an immutable URL
plus integrity prevents an upstream template change from silently changing an existing pipeline.
The template adds two .pre jobs:
compatibility.fyi/gateevaluates Renovate branch pipelines and applies the configured allow/warn/block policy when compatibility is unknown or cannot be checked;compatibility.fyi/recheckruns only in a scheduled default-branch pipeline and retriggers the existing Renovate branch pipelines.
Both jobs inherit only default runner tags, so consumer setup scripts, services, hooks, and caches are not applied to the gate. Global variables remain available for the configuration below.
GitLab does not create a pipeline that contains only jobs in the special .pre and .post stages.
Most projects already have an ordinary build, test, or deploy job, which satisfies this requirement.
If the gate is the repository's first CI configuration, add one job in a regular stage (or use an
existing stage from your pipeline):
"compatibility.fyi/pipeline-anchor":
stage: test
image: alpine:3.23.2
script:
- echo "The compatibility pipeline is active."Use the same platform-independent Renovate setting:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"prCreation": "status-success"
}Renovate creates its branch, waits for the GitLab pipeline to become green, and opens the merge request on a later run.
A pipeline schedule is required if unchanged Renovate branches should be rechecked and unblocked automatically. New or updated Renovate branches run the gate immediately, but a push to the default branch or a compatibility.fyi metadata change does not rerun existing branch pipelines. Renovate only reads their current status. Without a schedule, rechecking requires a branch update or a manual pipeline run.
GitLab schedules are project settings and cannot be created by include:remote. Configure one for
each repository that uses the gate:
- In Settings > CI/CD > Pipeline trigger tokens, create a trigger token.
- Save its value under Settings > CI/CD > Variables as
COMPATIBILITY_FYI_GITLAB_TRIGGER_TOKEN, marked Masked and Protected. - Create a pipeline schedule targeting the protected default branch, for example every six hours.
The scheduled job uses the built-in CI_JOB_TOKEN only to list branches and the narrowly scoped
trigger token only to start new pipelines. The trigger token is not needed by Renovate branch jobs
and must never be written into .gitlab-ci.yml.
The template supports these optional project or pipeline variables:
| Variable | Default | Description |
|---|---|---|
COMPATIBILITY_FYI_CONFIG_FILE |
.gitlab/compatibility-fyi.yaml |
Configuration path on the default branch. |
COMPATIBILITY_FYI_API_URL |
configuration/default | Compatibility API endpoint override. |
COMPATIBILITY_FYI_BASE_BRANCH |
CI_DEFAULT_BRANCH |
Default branch override. |
COMPATIBILITY_FYI_BRANCH_PATTERN |
renovate/** |
Minimatch glob used by evaluation and recheck. |
COMPATIBILITY_FYI_BRANCH_REGEX |
/^renovate\\// |
Matching GitLab rules regular expression. |
COMPATIBILITY_FYI_IMAGE |
release-specific public GHCR image | Gate container image override. |
When changing the branch convention, update both the glob and regular expression. You may pin
COMPATIBILITY_FYI_IMAGE to an image digest for an additional supply-chain lock.
The default configuration path is .github/compatibility-fyi.yaml on GitHub and
.gitlab/compatibility-fyi.yaml on GitLab. The file is always read from the default branch so a
dependency update cannot weaken its own policy.
| Field | Required | Description |
|---|---|---|
version |
yes | Configuration schema version. Must be 1. |
gates |
yes | One or more compatibility gates. |
api |
no | API endpoint, timeout, and retry settings. |
defaults |
no | Policy inherited by every gate. |
Unknown fields are rejected to prevent misspelled policies from silently bypassing the gate.
| Field | Required | Description |
|---|---|---|
id |
yes | Unique lowercase-dash identifier used in logs and summaries. |
project.id |
yes | Project identifier returned by /api/v1/projects. |
project.version |
yes | Selector that must resolve to exactly one resulting project version. |
dependency.id |
yes | Dependency key from the compatibility project document. |
dependency.versions |
yes | Selector returning one or more resulting dependency versions. |
policy |
no | Per-gate policy overrides. |
If a branch removes every selected dependency, the applicable gate passes because no relationship remains to check. If selected dependencies remain, the project selector must resolve to exactly one version.
Both project.version and dependency.versions use the same selector shape:
| Field | Required | Description |
|---|---|---|
files |
yes | One or more Minimatch globs evaluated against repository-relative file paths. |
document |
no | Dot-path/value pairs used to select documents from multi-document YAML files. |
value |
yes | Dot path to the scalar version value. Numeric array indexes are supported. |
extract |
no | Regular expression with a named version group or first capture group. |
helm |
no | Resolve an exact chart version to its appVersion using a static repository and chart. |
Examples:
# Read a direct scalar.
value: spec.ref.tag
# Extract 18.4 from ghcr.io/cloudnative-pg/postgresql:18.4.
value: spec.imageName
extract: ":(?<version>[^@]+)$"
# Select only one object from a multi-document file.
document:
kind: HelmRelease
metadata.name: cloudnative-pgTo resolve a Flux HelmRelease’s chart version to the application version used by the compatibility
API, add a helm source to the selector:
files:
- apps/gitlab/helmrelease.yaml
document:
kind: HelmRelease
metadata.name: gitlab
value: spec.chart.spec.version
helm:
repository: https://charts.gitlab.io
chart: gitlabThe selector reads an exact chart version such as 10.3.2 and looks up that entry’s appVersion
in the repository’s index.yaml. If extract is present, it runs before the lookup. Repository and
chart names come from the gate configuration on the default branch, rather than the selected
manifest. Both project and dependency selectors support this option. Use it when the chart’s
appVersion represents the deployed application; explicit image overrides require an image selector.
Repositories must be public HTTPS Helm repositories without credentials, query strings, or fragments.
OCI registries and redirects are not supported. Each repository index is fetched once per run and
shared across selectors and branches, with a 15-second timeout and a 32 MiB response limit. The gate
never downloads or executes a chart. Chart ranges and partial versions are rejected; missing, empty,
or conflicting appVersion metadata blocks evaluation without a fallback to another chart version.
Selectors are limited to 256 matching files and 100 unique values per branch evaluation.
| Field | Default | Description |
|---|---|---|
unknown |
block |
allow, warn, or block when compatibility.fyi returns unknown. |
apiError |
block |
allow, warn, or block when the API is unavailable or malformed. |
minimumConfidence |
high |
Minimum accepted evidence level: low, medium, or high. |
maximumEvidenceAgeDays |
unset | Maximum age of the API response's lastVerified date. |
Defaults can be shared and overridden by individual gates:
defaults:
unknown: warn
apiError: block
minimumConfidence: high
maximumEvidenceAgeDays: 180api:
url: https://compatibility.fyi/api/v1/check
timeoutSeconds: 10
retries: 2Remote endpoints must use HTTPS. Plain HTTP is accepted only for localhost development.
| Input | Default | Description |
|---|---|---|
config-file |
.github/compatibility-fyi.yaml |
Configuration path on the default branch. |
api-url |
configuration/default | Compatibility API endpoint override. |
mode |
auto |
current, all, or event-derived auto. |
branch-pattern |
renovate/** |
Renovate branch glob. |
base-branch |
repository default | Base branch override. |
status-context |
compatibility.fyi/gate |
Published commit status context. |
The underlying action additionally requires github-token; the reusable workflow supplies
github.token with only the declared permissions.
| Output | Description |
|---|---|
evaluated-branches |
Number of branches evaluated. |
blocked-branches |
Number of branches receiving failure or error. |
warned-branches |
Number of branches receiving a non-blocking warning. |
result |
Overall result: success, warning, or blocked. |
The action step does not fail merely because compatibility is blocked. Consumers should use the published commit status as the policy signal.
The reusable workflow is recommended. For custom workflows, check out the complete repository history and invoke the action directly:
permissions:
contents: read
statuses: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- uses: compatibility-fyi/compatibility-gate@v1
with:
github-token: ${{ github.token }}
mode: currentEvery run writes a GitHub Actions step summary containing:
- the branch and gate;
- project and dependency versions;
- compatibility result, evidence basis, and matched range or exact-version constraint;
- confidence and
lastVerifieddate; - links to primary sources returned by compatibility.fyi.
The commit status links back to the workflow run.
GitHub has no warning commit-status state, so warn publishes a successful status whose
description begins with Warning:, emits a workflow warning annotation, and records warning in
the summary and outputs. GitLab exits with code 2 for warn; the supplied template marks only that
exit code as allowed to fail, producing an orange warning without blocking Renovate. Explicit
incompatibility, insufficient confidence, and stale evidence always remain blocking.
GitLab writes the same decision and primary-source details to the compatibility.fyi/gate job log.
The job succeeds only when every applicable gate passes.
- Policy is loaded from the default branch, not the Renovate branch.
- The action only reads Git objects and YAML; it does not execute consumer scripts or install consumer dependencies.
- The workflow needs only
contents: readandstatuses: write. - GitLab branch jobs receive no compatibility.fyi or GitLab API secret. Only the protected scheduled recheck job receives its pipeline trigger token.
- API and GitHub responses are size-limited and validated before use.
- Unknown data and operational failures block by default.
- Consumer workflows should pin actions, reusable workflows, and remote templates to full commit
SHAs. GitLab remote includes should also use
integrity. - Do not use
pull_request_targetfor this gate.
See SECURITY.md for vulnerability reporting.
- Renovate still creates a branch before the gate runs. The gate prevents Renovate from opening the pull request.
- Renovate opens an allowed pull request on its next run, not immediately when the status turns green.
- This external gate evaluates the candidate Renovate selected. It cannot make Renovate fall back from an incompatible newest release to an older compatible release. Native Renovate enrichment would be needed for candidate filtering.
- The action evaluates repository-declared desired state, not the live cluster.
- If the default branch changes after a Renovate branch was created, Renovate may need to rebase the branch before the gate sees the new desired-state version.
- The GitLab integration is a public GitHub-hosted remote template, not a native GitLab CI/CD Catalog component.
- Confirm the workflow is present on the default branch.
- Do not use a
pathsfilter. - Confirm Actions are allowed to grant
statuses: write. - Check that the branch matches
renovate/**or your configured pattern. - Run the workflow manually with
mode: all.
On GitLab, confirm the remote include loaded, the branch matches both
COMPATIBILITY_FYI_BRANCH_PATTERN and COMPATIBILITY_FYI_BRANCH_REGEX, and a branch pipeline was
created.
Retry its pipeline, or configure the scheduled recheck job and verify that
COMPATIBILITY_FYI_GITLAB_TRIGGER_TOKEN is available to schedules on the protected default branch.
The failed historical pipeline remains visible, but the new successful job result is what Renovate
uses for the branch.
The selected project and dependency values did not change between the default branch and the
Renovate branch. Check files, document, value, and extract against the repository layout.
project.version must identify exactly one resulting version. Tighten its file glob or document
selector.
The API's optional reason field distinguishes missing project IDs, missing project
versions, missing dependency keys, uncovered dependency versions, recommendation-only
or bundle-only evidence, and an explicitly unknown upstream result. The gate includes
that distinction in its status description and detailed summary. Older API endpoints
without reason remain supported and receive a generic diagnostic.
Inspect the project document and dependency key:
curl https://compatibility.fyi/api/v1/projects/cloudnativepgCheck whether the result is uncovered, recommended, or bundled. A matching range does not by itself
establish compatibility. Inspect the current project index if a project was renamed or a matrix was
withdrawn. Do not change unknown to allow merely to suppress missing metadata; prefer contributing
source-backed support or test evidence.
Requires Node.js 24.
npm ci
npm run validate
git diff --exit-code -- distThe Node action is bundled into dist/ so consumers do not run npm install. The generated bundle
must be committed with source changes.