Custom Manager Support using JSONata
Categories: custom
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:
managerFilePatternsworks the same as any managermatchStringsis aJSONatacustom 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
currentValueof the dependency or use thecurrentValueTemplatetemplate field - Capture the
depNameorpackageName. Or use a template field:depNameTemplateandpackageNameTemplate - Capture the
datasource, or use thedatasourceTemplatetemplate field
Optional fields you can include in the resulting structure¶
You may use any of these items:
depType, or use thedepTypeTemplatetemplate fieldversioning, or the useversioningTemplatetemplate field. If neither are present, Renovate defaults tosemver-coercedextractVersion, or use theextractVersionTemplatetemplate fieldcurrentDigestregistryUrl, or use theregistryUrlTemplatetemplate field. If it's a valid URL, it will be converted to theregistryUrlsfield as a single-length arrayindentation. Must be empty, or whitespace. Else Renovate restes onlyindentationto 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:
- Read the official JSONata query language docs
- Check our example queries below
- 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 }