In private-isu, we used MySQL 8.4 in Docker Compose.
mysql:
image: mysql:8.4
However, the default Renovate configuration created a pull request to update MySQL to 26.7.
https://github.com/catatsuy/private-isu/pull/1107
- image: mysql:8.4
+ image: mysql:26.7
MySQL 26.7 is an Innovation release. We do not want to follow the latest release. We want to follow the latest LTS release.
To do this, I added a Renovate custom datasource that tells Renovate which version is the current MySQL LTS.
https://github.com/catatsuy/private-isu/pull/1108
Why not use mysql:lts?
The official MySQL Docker image provides an lts tag.
mysql:
image: mysql:lts
However, lts is a mutable tag.
When lts changes from 8.4 to 9.7, nothing changes in the Compose file. The next time the image is pulled, the MySQL release series may change without anyone noticing.
We do not want to automatically follow the lts tag at runtime. We want Renovate to notify us with a pull request when the LTS version changes.
- image: mysql:8.4
+ image: mysql:9.7
Reading the Docker Official Images file
Docker Official Images manages the MySQL tags in this file:
https://github.com/docker-library/official-images/blob/master/library/mysql
The file is not JSON and does not come from an API. It is plain text.
Tags: 26.7.0, 26.7, 26, innovation, latest, ...
Tags: 9.7.2, 9.7, 9, lts, ...
Tags: 8.4.11, 8.4, 8, ...
Renovate reads this file, finds the line containing lts, and extracts 9.7.
Reading text with format: "plain"
I configured the custom datasource like this:
{
"customDatasources": {
"mysql-lts": {
"defaultRegistryUrlTemplate": "https://raw.githubusercontent.com/docker-library/official-images/master/library/mysql",
"format": "plain",
"transformTemplates": [
"( $ltsLine := releases.version[$substring($, 0, 6) = 'Tags: ' and $contains(', ' & $substringAfter($, 'Tags: ') & ', ', ', lts, ')][0]; $minor := $split($substringAfter($ltsLine, 'Tags: '), ', ')[$match($, /^\\d+\\.\\d+$/)][0]; { 'releases': $minor ? [{ 'version': $minor }] : [] } )"
]
}
}
}
The important part is format: "plain".
The source is not structured JSON. With plain, Renovate reads the file line by line and roughly converts it into this structure:
{
"releases": [
{
"version": "Tags: 26.7.0, 26.7, 26, innovation, latest, ..."
},
{
"version": "Tags: 9.7.2, 9.7, 9, lts, ..."
}
]
}
The data is then processed by transformTemplates.
Extracting the LTS version with JSONata
transformTemplates uses JSONata.
JSONata is a language for querying and transforming JSON data. You can think of it as a way to write a query and a transformation in one expression.
The expression does four things:
- Find a line that starts with
Tags:and containslts - Split the line by commas
- Find a version such as
9.7that matchesnumber.number - Return it in Renovate’s release format
The result looks like this:
{
"releases": [
{
"version": "9.7"
}
]
}
Renovate can then compare 9.7 with the 8.4 version in the Compose file and create an update pull request.
Disable the standard Docker manager
The standard Docker Compose manager also detects the MySQL image in the Compose file.
Without extra configuration, the custom datasource suggests 9.7, while the standard Docker datasource suggests 26.7.
To avoid this, I disabled the standard manager only for MySQL in this file.
{
"matchManagers": ["docker-compose"],
"matchDatasources": ["docker"],
"matchPackageNames": ["mysql"],
"matchFileNames": ["webapp/compose.yml"],
"enabled": false
}
Disable minimumReleaseAge
private-isu has this global setting to avoid versions immediately after release:
{
"minimumReleaseAge": "2 days"
}
However, this custom datasource does not return release dates.
Without another rule, the update remains pending. I therefore set minimumReleaseAge to 0 days only for this datasource.
{
"matchDatasources": ["custom.mysql-lts"],
"matchPackageNames": ["mysql"],
"matchFileNames": ["webapp/compose.yml"],
"minimumReleaseAge": "0 days"
}
Renovate created the expected LTS update
After merging the configuration, Renovate created the expected pull request.
https://github.com/catatsuy/private-isu/pull/1109
- image: mysql:8.4
+ image: mysql:9.7
Instead of using mysql:lts directly, Renovate watches the version referenced by the lts tag.
This prevents the MySQL release series from changing without a visible code change.
Pinning the patch version
In private-isu, we pin the image to a version such as 9.7.
image: mysql:9.7
With this format, an update from 9.7.1 to 9.7.2 does not change the Compose file.
To review patch updates in pull requests, the same approach can extract the full version, such as 9.7.2.
Change the JSONata version pattern to:
^\d+\.\d+\.\d+$
The Compose configuration must also read the full version:
(?<currentValue>\d+\.\d+\.\d+)
Renovate can then create pull requests for patch updates.
- image: mysql:9.7.1
+ image: mysql:9.7.2
Use 9.7 when you only want to review changes to the LTS release series. Use 9.7.2 when you also want to review patch updates.
Renovate custom datasources make it possible to track mutable tags such as lts and stable without using those tags at runtime. Instead, changes to the version behind the tag are managed as pull requests.
Top comments (0)