Files
Jamie Tanna 8abbd14fe6 fix(config/validation): allow only capturing currentDigest in Custom Managers (#45671)
* fix(config/validation): allow only capturing `currentDigest` in Custom Managers

As reported in #45665, it was previously possible - through a preset
prior to 44.60.1 - to specify a Custom Manager (in this case, with
Regex) that only captured the `currentDigest` for a dependency.

This causes config validation in a repository, but as it appears to be
valid - with `currentValue` defaulting to `latest` - we should make it
possible to use either `currentValue` or `currentDigest`.

* fixup! fix(config/validation): allow only capturing `currentDigest` in Custom Managers
2026-09-04 11:30:15 +00:00
..

With customManagers using JSONata queries you can configure Renovate so it finds dependencies in JSON, TOML and YAML files, that are not detected by its other built-in package managers.

Renovate uses the jsonata package to process the file content using the queries, after the content has been parsed into json format.

For more on the jsonata query language, read the jsonata query language site.

The JSONata manager is unique in Renovate, because:

  • It can be used with any datasource
  • It can be configured via JSONata queries
  • You can create multiple "JSONata managers" in the same repository

If you have limited managers to run within enabledManagers config option, you need to add "custom.jsonata" to the list.

Required Fields

The first two required fields are managerFilePatterns and matchStrings:

  • managerFilePatterns works the same as any manager
  • matchStrings is a JSONata custom manager concept and is used for configuring a jsonata queries

Information that Renovate needs about the dependency

Before Renovate can look up a dependency and decide about updates, it must have this info about each dependency:

Info type Required Notes Docs
Name of the dependency Yes
datasource Yes Example datasources: npm, Docker, GitHub tags, and so on. Supported datasources
Version scheme to use. Defaults to semver-coerced. Yes You may set another version scheme, like pep440. Supported versioning schemes
fileFormat Yes Must be either json, yaml or toml. Configuration Options

Required fields to be present in the resulting structure returned by the jsonata query

You must:

  • Capture the currentValue or currentDigest of the dependency or use the currentValueTemplate or currentDigestTemplate template field
  • Capture the depName or packageName. Or use a template field: depNameTemplate and packageNameTemplate
  • Capture the datasource, or use the datasourceTemplate template field

Optional fields you can include in the resulting structure

You may use any of these items:

  • depType, or use the depTypeTemplate template field
  • versioning, or the use versioningTemplate template field. If neither are present, Renovate defaults to semver-coerced
  • extractVersion, or use the extractVersionTemplate template field
  • registryUrl, or use the registryUrlTemplate template field. If it's a valid URL, it will be converted to the registryUrls field as a single-length array
  • indentation. Must be empty, or whitespace. Else Renovate restes only indentation to an empty string

Usage

When you configure a JSONata manager, use the following syntax:

{
  "customManagers": [
    {
      "customType": "jsonata",
      "fileFormat": "json",
      "managerFilePatterns": ["<file match pattern>"],
      "matchStrings": ["<query>"],
      ...
    }
  ]
}

Overwrite the <query> placeholder text with your JSONata query. The JSONata query transforms the content to a JSON object, similar to this:

[
  {
    "depName": "some_dep",
    "currentValue": "1.0.0",
    "datasource": "docker",
    "versioning": "semver"
  }
]

Creating your Renovate JSONata manager config is easier if you understand JSONata queries. We recommend you follow these steps:

  1. Read the official JSONata query language docs
  2. Check our example queries below
  3. You're ready to make your own config

Alternatively, you can use "trial and error" to a working config by adjusting our examples.

YAML files are parsed as multi-document files, even those that have only one document.

YAML parsing

To show how the JSONata manager parses YAML, below is an example YAML file and the corresponding parsing to JSON.

YAML:

production:
  packages:
    version: 1.2.3
    package: foo
test:
  metadata:
    - version: 4.5.6
      package: bar
---
development:
  author: Renovate

JSON:

[
  {
    "production": {
      "packages": {
        "version": "1.2.3",
        "package": "foo"
      }
    },
    "test": {
      "metadata": [
        {
          "version": "4.5.6",
          "package": "bar"
        }
      ]
    }
  },
  {
    "development": {
      "author": "Renovate"
    }
  }
]

Example queries

Below are some example queries for the generic JSON manager. You can also use the JSONata test website to experiment with queries.

{
  "production": [
    {
      "version": "1.2.3",
      "package": "foo"
    }
  ],
  "development": [
    {
      "version": "4.5.6",
      "package": "bar"
    }
  ]
}

Query:

production.{ "depName": package, "currentValue": version }
{
  "production": [
    {
      "version": "1.2.3",
      "package": "foo"
    }
  ],
  "development": [
    {
      "version": "4.5.6",
      "package": "bar"
    }
  ]
}

Query:

*.{ "depName": package, "currentValue": version }
{
  "foo": {
    "version": "1.2.3"
  },
  "bar": {
    "version": "4.5.6"
  }
}

Query:

$each(function($v, $n) { { "depName": $n, "currentValue": $v.version } })
{
  "packages": [
    {
      "version": "1.2.3",
      "package": "foo"
    },
    {
      "version": "4.5.6",
      "package": "bar"
    }
  ]
}

Query:

packages.{ "depName": package, "currentValue": version }
{
  "packages": ["foo@1.2.3", "bar@4.5.6"]
}

Query:

$map($map(packages, function ($v) { $split($v, "@") }), function ($v) { { "depName": $v[0], "currentVersion": $v[1] } })
{
  "customManagers": [
    {
      "customType": "jsonata",
      "fileFormat": "json",
      "managerFilePatterns": ["/package.json/"],
      "matchStrings": [
        "$each(dependencies, function($v, $k) { {\"depName\":$k, \"currentValue\": $v, \"depType\": \"dependencies\"}})",
        "$each(devDependencies, function($v, $k) { {\"depName\":$k, \"currentValue\": $v, \"depType\": \"devDependencies\"}})",
        "$each(optionalDependencies, function($v, $k) { {\"depName\":$k, \"currentValue\": $v, \"depType\": \"optionalDependencies\"}})",
        "{ \"depName\": \"pnpm\", \"currentValue\": $substring(packageManager, 5),  \"depType\": \"packageManager\"}"
      ],
      "datasourceTemplate": "npm"
    }
  ]
}
packages:
  - version: 1.2.3
    package: foo

Query:

packages.{ "depName": package, "currentValue": version }
packages:
  - version: 1.2.3
    package: foo
---
packages:
  - version: 1.2.5
    package: bar

Query:

packages.{ "depName": package, "currentValue": version }
[[packages]]
version = "1.2.3"
package = "foo"

[[packages]]
version = "1.2.2"
package = "bar"

Query:

packages.{ "depName": package, "currentValue": version }