allowedVersions: "<6" silently broken by github-actions versioning change
#42824
-
How are you running Renovate?A Mend.io-hosted app Which platform you running Renovate on?GitHub.com Which version of Renovate are you using?unknown exact version — issue started April 16 Please tell us more about your question or problem(AI generated, human reviewed) What happenedWe use a shared Renovate preset across ~200 repos with this rule to block a new major version of a GitHub action: {
"matchManagers": ["github-actions"],
"matchPackageNames": ["actions/checkout"],
"allowedVersions": "<6"
}This worked correctly when merged on March 25 — Renovate closed all existing Starting April 16, Renovate began reopening/creating The bug
Root cause analysisThe
The new Here's why — tracing through Step 1 — const isAllowedPred = getRegexPredicate(allowedVersions);
if (isAllowedPred) { // ← "<6" is not a regex, skip
} else if (versioningApi.isValid(allowedVersions)) { // ← THIS is the problem branch
filteredReleases = filteredReleases.filter((r) =>
versioningApi.matches(r.version, allowedVersions), // ← uses versioning's matches()
);
} else if (... semver.validRange(allowedVersions)) { // ← correct semver fallback, never reachedStep 2 — function isValid(input: string): boolean {
return !!parseVersion(input) || !!parseRange(input); // parseVersion("<6") = null, but parseRange("<6") = truthy!
}Step 3 — function parseRange(input: string): Range | null {
const stripped = massageValue(input); // massageValue("<6") = "<6" (only strips leading "v")
const coerced = semver.coerce(stripped); // semver.coerce("<6") = SemVer{6,0,0} — coerce extracts "6" from ANY string!
if (!coerced) { return null; }
const { major, minor } = coerced; // major=6, minor=0
if (regEx(/^\d+$/).test(stripped)) { // "<6" doesn't match /^\d+$/, falls through
return { major };
}
return { major, minor }; // returns { major: 6, minor: 0 } ← WRONG, "<6" is not a floating tag
}Step 4 — back in function matches(version: string, range: string): boolean {
// #42809 early return: massageValue("v6.0.1")="6.0.1" ≠ massageValue("<6")="<6", skip
const v = parseVersion(version); // parseVersion("v6.0.1") = SemVer{6,0,1}
const rv = parseVersion(range); // parseVersion("<6") = null, skip
const r = parseRange(range); // parseRange("<6") = { major: 6, minor: 0 } (same as step 3)
// ...
if (v.major !== r.major) return false; // 6 === 6, continue
if (isUndefined(r.minor)) return true; // r.minor = 0 (defined), continue
return v.minor === r.minor; // 0 === 0 → true ← v6.0.1 ALLOWED through ❌
}Previously with Suggested fix
function parseRange(input: string): Range | null {
const stripped = massageValue(input);
// Only accept valid floating tags: "1", "1.2" (with optional "v" prefix, handled by massageValue)
// Reject semver range operators that semver.coerce() would incorrectly extract numbers from
if (!regEx(/^\d+(\.\d+)?$/).test(stripped)) {
return null;
}
// ... rest of existing logic
}Minimal reproductionUse this {
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"packageRules": [
{
"description": "Block actions/checkout v6+",
"matchManagers": ["github-actions"],
"matchPackageNames": ["actions/checkout"],
"allowedVersions": "<6"
}
]
}With a workflow file like name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5Expected: No PR created for Actual: Renovate creates a PR to update This affects any WorkaroundUsing a regex for "allowedVersions": "/^v?[0-5]/"Logs (if relevant)Not applicable, found by AI investigation without access to logs. If needed I can find some though. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Thanks - should be fixed by #42831 |
Beta Was this translation helpful? Give feedback.
Thanks - should be fixed by #42831