* ci(linter): add renovate/require-regex-util rule Adds a custom oxlint rule that flags raw RegExp usage in lib/ production code: any `new RegExp(...)` call and any regex literal that is not the direct first argument of `regEx(...)`. The regEx() helper from lib/util/regex.ts uses the RE2 engine for ReDoS-safe matching and caches compiled patterns. lib/util/regex.ts itself is exempt. The rule is disabled for **/*.spec.ts, test/**, and tools/** via config overrides, because vitest APIs such as expect.stringMatching need bare RegExp instances (a past commit reverted regEx() there). Severity is set to "warn" instead of "error": the repo currently has 197 pre-existing violations (above the agreed mechanical-fix threshold of 80), and a number of them are deliberately RE2-incompatible patterns (lookahead/lookbehind/named backreferences, see TODO #12872/#12875 markers in e.g. lib/modules/versioning/rez/ pattern.ts and lib/modules/manager/dockerfile/extract.ts) that need per-site judgment before they can be wrapped in regEx() or suppressed with a justified disable comment. No violation fixes are included in this commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(linter): enforce renovate/require-regex-util at error Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: use regEx() for regex literals and RegExp construction in lib Burn down all renovate/require-regex-util violations (197): - wrap RE2-compatible regex literals and RegExp constructions in regEx() - rewrite lookaround patterns where behavior is provably preserved: goproxy separator split, sbt-package link extraction, leiningen comment stripping and keyword search, npm GitHub owner validation (unit-count bound replaced by an explicit length check) - keep native RegExp with disable comments where RE2 cannot be used: moo / good-enough-parser lexer patterns (moo rejects RE2 instances), MigrationsService propertyName (matched via isRegExp, which RE2 instances fail), rez named backreferences and lookaheads, GitHub markdown link negative lookbehind, emoji astral-plane matching - drop stale TODO #12875 comments for patterns current re2 handles Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: reduce require-regex-util disable comments Rewrite the github massage-markdown-links URL regex to capture an optional `api.` prefix in a named group (skipped in code) instead of relying on a negative lookbehind, so both the base and global variants can use regEx()/RE2 and their two disable comments are removed. Add spec cases for api-prefixed URLs that match the URL shape. Consolidate the four related line disables in rez/pattern.ts (bound and range patterns emulating Python conditional patterns via named backreferences and lookaheads, which RE2 cannot express) into a single block disable/enable pair, matching the treatment of the lexer files. Disable comment count drops from 13 to 8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(datasource/sbt-package): use named capture group in link regex Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(manager/cake): restore original multiLineComment regex spelling The [^] -> [\\s\\S] rewrite was only needed for an RE2 wrap that was later reverted; keep the diff minimal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(datasource/go): skip empty GOPROXY segments The switch from a lookahead split to a capture-group split (needed because RE2 has no lookahead support) changed how empty GOPROXY segments parse: `a|,b` yielded `{ url: ',', fallback: '|' }` before and `{ url: '', fallback: ',' }` after. The comma fallback only continues on 404/410, so a failing proxy ahead of an empty segment silently stopped the lookup instead of falling through to the remaining proxies. Empty segments carry no url to query, so drop them. * refactor(datasource/go): use isTruthy for empty segment filter * fix(datasource/go): filter empty segments before mapping Filtering after the map broke the contextual typing from the GoproxyItem[] annotation, widening fallback to string. * refactor(platform/github): use regEx() for merge queue query stripping --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This datasource rpm returns releases of the RPM packages.
It assumes the RPM repository is following the RPM standard and by default it has a repomd.xml in the directory provided by user in the registryUrl.
According to this Pulp project doc, https://docs.pulpproject.org/en/2.10/plugins/pulp_rpm/tech-reference/rpm.html,
repomd.xml is the metadata file that clients use to discover what repository metadata files exist in the repository. It should always be located at repodata/repomd.xml relative to the root of the repository.
Set URL when using an RPM repository
To use an RPM repository with the datasource, you must set a registryUrl with the directory that contains the repomd.xml and corresponding primary.xml.
Example:
If we have
http://example.com/repo/repodata/repomd.xmlhttp://example.com/repo/repodata/<SHA256>-primary.xmlwhere<SHA256>is a dynamically generated SHA256 pattern.
Then the registryUrl should set as http://example.com/repo/repodata/ or http://example.com/repo/repodata.
Usage Example
Say you're defining dnf/tdnf/yum packages in a manifest.json and you want Renovate to update them.
Assuming your manifest.json looks like this.
{
"example-package1": "1.0.0-1.azl3",
"example-package2": "1.1.0"
}
where the versioning format could be <semantic version>-<revision or release>, or just <semantic version>
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": [
"path_to_manifest_json"
],
"registryUrlTemplate": "http://example.com/repo/repodata/",
"datasourceTemplate": "rpm"
}
]
}
In an RPM repository, the <SHA256>-primary.xml looks like this:
`<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://linux.duke.edu/metadata/common">
<package type="rpm">
<name>example-package1</name>
<arch>x86_64</arch>
<version epoch="0" ver="1.0" rel="2.azl3"/>
</package>
<package type="rpm">
<name>example-package1</name>
<arch>x86_64</arch>
<version epoch="0" ver="1.1" rel="1.azl3"/>
</package>
<package type="rpm">
<name>example-package1</name>
<arch>x86_64</arch>
<version epoch="0" ver="1.1" rel="2.azl3"/>
</package>
<package type="rpm">
<name>example-package1</name>
<arch>x86_64</arch>
<version epoch="0" ver="1.2"/>
</package>
...
...
</metadata>
You may also check the yum/dnf info for the package to find version and release:
# dnf info example-package1
Last metadata expiration check: 18:34:13 ago on Tue Oct 7 13:58:36 2025.
Installed Packages
Name : example-package1
Version : 1.0.0
Release : 1.azl3
Architecture : x86_64
[...]
You can see that ver and rel (release/revision) is stored separately.
The RPM datasource implementation will combine these together as ver-rel.
That's why the version is defined as 1.0.0-1.az3, if rel (like example-package1) is available.
Or just 1.1.0 if rel (like example-package2) is not available.
Limitation and Consideration
In real-world scenarios, the decompressed primary.xml file from an RPM repository can be extremely large.
To handle this efficiently, this implementation uses streaming XML parsing, which processes the file incrementally and avoids loading the entire XML into memory.
Streaming XML parsing is a practical solution for large files in Node.js, but for extremely large or complex cases (e.g., files exceeding ~512MB), you may still encounter memory or performance issues. For such scenarios, consider using more robust approaches such as native modules, optimized SAX parsers, or external tools. Contributions and suggestions for further improving large file handling are welcome.