Files
Gregor Zeitlinger 0d9888a4f2 feat(datasource): add GraalVM version datasource (#40497)
* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases

* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases

* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases

* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases

* feat(datasource): add GraalVM version datasource with support for JDK and JRE releases

* add coverage

* fix

* fix

* fix

* code cov

* code cov

* code cov

* refactor(datasource): integrate GraalVM into java-version datasource

Merges graalvm-version datasource into java-version as a unified multi-vendor
Java distribution datasource. Implements vendor-based modular architecture with
routing layer for Adoptium (Eclipse Temurin) and Oracle GraalVM.

Architecture:
- Vendor-specific handlers (adoptium.ts, graalvm.ts) with routing in index.ts
- Vendor-aware system detection with different arch/os mappings per vendor
- Custom registry support for GraalVM's mise-java API
- Adoptium remains the default registry for backwards compatibility

Package names:
- New explicit: adoptium-jdk, adoptium-jre, oracle-graalvm-jdk, oracle-graalvm-jre
- Legacy (map to Adoptium): java, java-jdk, java-jre

Changes:
- Created adoptium.ts and graalvm.ts vendor handlers
- Enhanced common.ts with vendor detection and vendor-specific system mappings
- Updated index.ts with routing layer and custom registry support
- Merged test suites with comprehensive coverage for both vendors
- Updated mise manager integration to use JavaVersionDatasource
- Removed graalvm-version datasource directory

All 65 datasource tests and 93 mise manager tests passing.

* fix

* test(datasource): add coverage for non-HttpError paths in java-version

* fix(datasource): remove dead code and add coverage for java-version

Remove unreachable HttpError handling from _getReleases catch block
since both getAdoptiumReleases and getGraalvmReleases handle HttpError
internally. Add test for the graalvmRegistryUrl fallback when
registryUrl is undefined.

* fix(datasource): address review comments for GraalVM datasource

- Remove unused 'datasource-graalvm-version' cache namespace
- Convert MiseJavaRelease interface to Zod schema and derive type from it
- Use http.getJson() with the Zod schema in getGraalvmReleases instead
  of getJsonUnchecked, letting the schema handle invalid/empty responses
- Update getGraalvmReleases test mock to use getJson

* docs: remove unused datasource-graalvm-version from cacheTtlOverride docs

* fix(datasource): preserve Adoptium config typing

* fix(datasource): harden GraalVM release parsing

* fix(datasource): address GraalVM review feedback

* test: cover GraalVM mise package mapping

* test(datasource): cover default GraalVM registry fallback

* test(datasource): cover legacy registry resolution

* test(datasource): type legacy datasource mocks

* fix(datasource): harden GraalVM defaults and responses

* refactor(datasource): use function-only registry accessors

* test(datasource): cover registry accessor functions

* test: restore coverage exclusions

* chore: retrigger CI checks
2026-09-23 08:40:24 +00:00
..

The APK datasource is designed to work with Alpine Linux package repositories. It can fetch package information from APK repositories and provide version updates for Alpine Linux packages.

Alpine Linux uses the APK package manager, and packages are distributed through repositories. Each repository contains an APKINDEX.tar.gz file that contains metadata about all available packages.

Files are typically located in this structure:

https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz

Set URL when using an APK repository

To use an APK repository with the datasource, you must set a properly formatted URL with specific query parameters as registryUrl:

  • arch: Architecture of the binary packages (e.g. x86_64, aarch64, armv7).
  • branch: Alpine branch, either a rolling alias like latest-stable or edge, or a fixed release like v3.19. Omit this parameter for repositories which do not have a branch in their path.
  • components: Comma-separated list of repository components (e.g. main,community,testing). Omit this parameter for repositories which serve their index directly below the repository root.

!!! note Renovate does not fetch the registryUrl as-is. It combines the base URL with these parameters to build the actual index URLs, for example <base>/<branch>/<component>/<arch>/APKINDEX.tar.gz. Only the parameters above are accepted, so that a typo fails loudly instead of being ignored.

Examples:

https://dl-cdn.alpinelinux.org/alpine?branch=v3.19&components=main,community&arch=x86_64
https://packages.wolfi.dev/os?arch=x86_64

The first URL points to the v3.19 branch of the Alpine repository for the x86_64 architecture, including the main and community components. Renovate looks up the package in every component you list, and aggregates the releases it finds.

The second URL points to the Wolfi repository, which has no branch or component in its path.

How Renovate builds the index URLs

Say you set this registryUrl in your Renovate config:

{
  "packageRules": [
    {
      "matchDatasources": ["apk"],
      "registryUrls": [
        "https://dl-cdn.alpinelinux.org/alpine?branch=v3.19&components=main,community&arch=x86_64"
      ]
    }
  ]
}

Renovate then fetches one index per component:

https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz

Versioning

This datasource uses apk versioning by default, which follows Alpine's version format (3.2.1-r0, 2.39.0_rc1-r0, 6.5_p20250503-r0) and understands APK's version constraints.

This means a currentValue may be a constraint rather than a plain version, e.g. =~8.12.1 to accept any 8.12.1-rN. Read the apk versioning docs for the operators it supports.

Depending on which APK repository you are using, you may want to use the loose versioning scheme, like so:

{
  "packageRules": [
    {
      "matchDatasources": ["apk"],
      "versioning": "loose"
    }
  ]
}

Dockerfile support

When using distributions built on apk packages, it is common to use a version pin for your packages, like so:

FROM alpine:3.18
RUN apk add --no-cache bash=5.2.37-r2

This provides reproducibility in the case that the upstream package updates under you.

The dockerfile manager extracts these packages, allowing updates to them directly, without needing a Custom Manager.

The dockerfile manager does not work out a registryUrl from your base image, so it skips these packages with skipReason: unknown-registry rather than look them up against a registry which may hold versions your image cannot install. Set the registryUrls which match your base image with a packageRules entry to have them looked up.

{
  "packageRules": [
    {
      "matchFileNames": ["Dockerfile"],
      "matchDatasources": ["apk"],
      "matchPackageNames": ["nginx"],
      "registryUrls": [
        "https://dl-cdn.alpinelinux.org/alpine?branch=v3.18&components=main,community&arch=x86_64"
      ]
    }
  ]
}

Wolfi and Chainguard Images example

Wolfi serves its index directly below the repository root, so its registryUrl needs neither branch nor components - only arch:

{
  "packageRules": [
    {
      "matchDatasources": ["apk"],
      "registryUrls": ["https://packages.wolfi.dev/os?arch=x86_64"]
    }
  ]
}

Renovate then fetches a single index:

https://packages.wolfi.dev/os/x86_64/APKINDEX.tar.gz

Use arch=aarch64 for an arm64 image.

Pinning packages in a Wolfi image

As the Wolfi (un)distribution follows a rolling release cadence, it is common to pin the version of a package you depend on. Similarly, the package's revision (-rN) changes more often than its version.

For instance, you may have a Docker image like so:

FROM cgr.dev/chainguard/wolfi-base:latest@sha256:96ff486b326d15db16aa1fbd41a17043a557bebf76d2c0ac932e717534025940

RUN apk add --no-cache \
      curl=~8.12.1 \
      jq=1.7.1-r4 \
      bash

In this case:

  • curl=~8.12.1 is a prefix constraint, so it already accepts every 8.12.1-rN. Renovate doesn't propose an update while there are only revision-based updates. Once 8.13.0 exists, Renovate will provide an update to curl=~8.13.0.
  • jq=1.7.1-r4 is an exact pin, so Renovate raises a PR for a new revision (jq=1.7.1-r5) as well as for a new version (jq=1.8.0-r0).
  • bash has no version at all, so Renovate skips with skipReason: unsupported-version

Mixing Alpine and Wolfi in one repository

A registryUrl applies per lookup, so a repository holding both Alpine and Wolfi images needs the two scoped apart. Match on the file the dependency was found in:

{
  "packageRules": [
    {
      "matchDatasources": ["apk"],
      "registryUrls": [
        "https://dl-cdn.alpinelinux.org/alpine?branch=v3.21&components=main,community&arch=x86_64"
      ]
    },
    {
      "matchDatasources": ["apk"],
      "matchFileNames": ["**/*.wolfi", "**/Dockerfile.wolfi"],
      "registryUrls": ["https://packages.wolfi.dev/os?arch=x86_64"]
    }
  ]
}

A later rule overrides an earlier one, so set the repository you use most as the first rule and narrow it with the rules after it. Putting the narrower rule first would let the broader one overwrite its registryUrls again.