Taming Oracle Dependencies with Renovate
- Samuel Roberts

- Jun 11
- 5 min read
Custom dependency management for ORDS & Apex versus out of the box configurations
If you use Renovate, you know it's fantastic for standard ecosystems like npm, Maven, python, container images etc. What happens when you need to track enterprise dependencies that don't live in a neat registry? What if the only place a version number exists is buried in a paragraph on an AWS documentation page?
Recently, I set out to automate dependency updates for Oracle Rest Data Services (ORDS), SQLcl, and Oracle APEX. As you’d expect from a company with “APEX” in their name, we rely heavily on the tool to facilitate agile low code development. It’s therefore incredibly important that in any dependency management system we use must also update those three named resources.
Before I get into exactly how to do this, let me start by saying that this is exactly the blog post I wish I had had at my fingertips around a week ago. If someone else had taken the time to write this, it would have saved me more hours than I care to admit in debugging, documentation digging and wrestling with try.jsonata.org. I’m therefore starting to think that I must be the first person on the planet that needed to manage these dependencies with Renovate, so hopefully this can save you time. Moreover, this blueprint will act as the perfect building blocks for any other painful dependencies that just don’t want to play ball out of the box.
Okay, so without further ado, here is how I built custom managers and custom datasources to scrape HTML pages, parse raw text with JSONata, and bend Renovate's versioning engine at my will.
Let’s cover some Renovate terminology to get us going.
Custom Managers
For most dependencies, renovate works right out of the box as per my previous blog post. For those that don’t, we can configure a custom manager and use this to point at our code and say to renovate “hey, this is a dependency, you need to deal with this too”. In its most simple form, creating a custom manager and telling renovate to use one of the preconfigured datasources (more on these shortly) to decide how to version it and where to look for new versions will work just fine. For others (like the ones I’ll mention in this blog), we’ll need to create our own datasource too.
Data Sources
So what is a datasource in Renovate? A datasource is the thing that tells renovate where to go for the potential updates, what they look like and how they are versioned. Every custom Manager needs to reference a datasource, whether that’s a custom data source or the pre configured data sources that are shipped with Renovate.
Anyway, as the great Linus Torvalds said, “Talk is cheap, show me the code”.... It’s coming up in the next paragraph:
Scraping Oracle ORDS
Tracking Oracle ORDS and SQLcl was the perfect warm up. Oracle lists the available downloads on a standard webpage. The part of our code that needed updating was the ARG values inside our Dockerfiles.
Renovate actually has a built-in (ish) way to handle this: the html formatting within custom datasources. When you point Renovate to a webpage using "format": "html", it acts like a directory scraper, specifically looking for <a href> anchor tags to extract versions.
Because Oracle's download page uses standard hyperlinks for their ZIP files, this was relatively straightforward (massive lie, it still took ages to work out..).
The ORDS Configuration
1. The Custom Datasource:
I created an oracle-releases datasource that tells Renovate where to look and what format to expect.
{
"customDatasources": {
"oracle-releases": {
"description": "Custom datasource for Oracle releases (ORDS & SQLcl)",
"defaultRegistryUrlTemplate": "https://docs.oracle.com/en/database/oracle/oracle-rest-data-services",
"format": "html"
}
}
}2. The Custom Manager:
Next, we told Renovate how to find the current version inside our Dockerfile and link it to our new datasource.
{
"customManagers": [
{
"customType": "regex",
"description": "Update ORDS major & minor version in Dockerfile",
"fileMatch": ["(^|/)Dockerfile$"],
"matchStrings": [
"datasource=(?<datasource>.*?) depName=(?<depName>.*?)\\sARG ORDS_VERSION=(?<currentValue>.*)\\s"
],
"datasourceTemplate": "custom.oracle-releases",
"depNameTemplate": "oracle-ords",
"extractVersionTemplate": "^(?<version>\\d+\\.\\d+)"
}
]
}With a simple annotation comment above our Dockerfile ARG, Renovate successfully scraped the links, extracted the versions via regex, and opened our PRs.
# renovate: datasource=custom.oracle-releases depName=oracle-ords
ARG ORDS_VERSION=24.4
ARG ORDS_PATCH=.0.345.1601It was almost too easy to configure something similar for SQLcl, simply changing the url that renovate needs to visit for the update.
Advanced - Scraping AWS RDS Oracle APEX
While ORDS and SQLcl were quite difficult to configure, tracking the AWS RDS version of Oracle APEX was an absolute nightmare.
The exact string we needed to track (e.g. 24.2.v1) only exists on a specific AWS Documentation page (trust me, if there was a corner of the internet where it also existed, I’d have found it).
And AWS don't put it in a hyperlink; they just drop it in a plain text paragraph:
<p>Oracle APEX version 24.2.v1</p>Because there is no <a href> , Renovate's html datasource completely ignores it. It returns zero results. That is clear in the docs but many fine gentlemen would be forgiven for not noticing this (like I did).
The Solution: Plain Text and JSONata
To bypass the HTML parser, we had to use Renovate's plain format. When you use this format, Renovate downloads the raw HTML, splits it line-by-line, and loads it into memory as an array of objects. I know that because I looked at exactly what renovate is doing under the hood but it’s not abundantly clear from the docs that that is actually happening with HTML data, since the example in the docs is identical to a .txt file. That said, I got it working as follows:
To start with, locally transform the data into exactly what renovate sees when using the plain format. Running the following command will give you that format in a lovely json file.
curl -s https://<AWS_DOCS_URL_HERE> | jq -R '{version: .}' | jq -s '{releases: .}' > rds-payload.jsonI then used try.jsonata.org for what felt like a lifetime, wrestling with the data until it finally revealed itself. This post isn’t about JSONata, for a crash course in that, watch this video.
When our query works in that web page, we're ready to use JSONata inside a transformTemplates array to write a script that filters the raw HTML lines, runs a regex to extract the version numbers, and formats it back into the strict JSON schema Renovate requires.
{
"customDatasources":
{
"oracle-apex-releases": {
"description": "Scrapes raw AWS HTML for APEX versions",
"defaultRegistryUrlTemplate": "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.APEX.Requirements.html",
"format": "plain",
"transformTemplates": [
"{ \"releases\": $append([], releases[version ~> /[0-9]+\\.[0-9]+\\.v[0-9]+/].{ \"version\": $match(version, /[0-9]+\\.[0-9]+\\.v[0-9]+/)[0].match }) }"
]
}
}
}What the JSONata does:
1. It iterates through the thousands of HTML lines and acts as a strict boolean filter, keeping only the lines that contain our exact version format.
2. It runs a regex capture strictly on those surviving lines to extract just the string (e.g., "24.2.v1").
3. It forces the final output into a clean array, satisfying Renovate's strict data schema.
The Hidden Trap: Versioning Schemes
Once we finally got Renovate to see 24.2.v1, it still threw an error. Why? Because Renovate defaults to SemVer-coerced versioning.
24.2.v1 is an AWS-specific packaging suffix, not valid SemVer. Renovate's engine was stripping the .v1, coercing it to 24.2.0, and failing to map it back to our current codebase.
The fix was adding "versioningTemplate": "loose" to our custom manager, which tells Renovate to respect non-standard alphanumeric strings. In short, renovate now says “oh, this looks like the thing I’m trying to find. It must be it.”.
{
"customManagers": [
{
"customType": "regex",
"description": "Update AWS APEX version in CDK",
"fileMatch": ["\\.ts$"],
"matchStrings": [
"datasource=(?<datasource>.*?)\\s+depName=(?<depName>.*?)[\\s\\S]*?apexVersion:\\s*\"(?<currentValue>.*?)\""
],
"datasourceTemplate": "custom.oracle-apex-releases",
"extractVersionTemplate": "^(?<version>\\d+\\.\\d+\\.v\\d+)",
"versioningTemplate": "loose"
}
]
}The Takeaway
Renovate is incredibly powerful if you are willing to dig into its advanced features. By leveraging plain data formats, JSONata transformTemplates, and loose versioning, you can completely decouple yourself from standard package registries and automatically track dependencies hidden anywhere on the internet, on indeed in your local system if you have private, bespoke packages.




