Renovate 中的 Paket 版本约束:语法、预发布通道与范围重写策略 Renovate 中的 Paket 版本约束语法、预发布通道与范围重写策略【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate本篇技术指南聚焦 Renovate CLI 的paket版本化模块versioning module讲解它如何实现 Paket 的paket.dependencies版本约束语法包括完整的运算符表、预发布prerelease通道的匹配规则、!/解析策略前缀的处理以及replace/bump/widen三种范围重写策略的精确语义。读完本文后你将能够准确判断某个版本是否满足 Paket 范围、理解 Renovate 更新 Paket 依赖时为什么把范围改写成特定形状并能在配置中选择合适的rangeStrategy。为什么 Paket 需要独立的版本化模块Paket 是 F# 社区的 NuGet 依赖管理工具它的paket.dependencies文件有一套自己的版本约束语法。Renovate 在 模块定义文件 中为此实现了id paket的独立 versioning 模块原因在 模块说明文档 中说得清楚版本本身是 NuGet 版本Paket 版本的解析和比较与nuget版本化模块完全一致。从源码看index.ts 直接import { parseVersion } from ../nuget/parser.tsgetMajor/getMinor/getPatch/equals/sortVersions等都建立在 NuGet 版本解析器之上范围语法却与 NuGet 冲突Paket 的范围写法与 NuGet range 语法在重叠区间上语义相反。最典型的例子是裸版本号1.2.3——在 Paket 中它是精确钉住exact pin而在 NuGet range 语法中表示「至少1.2.3」。正是这个冲突决定了不能复用 nuget 模块的范围逻辑必须单独实现一套matches和getNewValue。模块声明supportsRanges true并在 supportedRangeStrategies 中显式列出支持的四种策略bump、widen、replace、update-lockfile。支持的约束语法全表parseRangerange.ts接受运算符 ~以及裸版本号并允许两个约束组合。支持的约束及其含义如下约束含义1.2.3或 1.2.3恰好等于1.2.3 1.2.3恰好等于1.2.3覆盖冲突override 1.2.3不低于1.2.3 1.2.3严格大于1.2.3 1.2.3不高于1.2.3 1.2.3严格小于1.2.3~ 1.2.3悲观约束pessimistic等价于 1.2.3且 1.3 1.2.3 1.5组合上下界~ 1.2 1.2.3悲观约束叠加下界floor解析器对「哪些双约束组合合法」有严格白名单见 isValidPair~后面可以接、、、或后面可以接或其他任何两约束组合如 1.2.3 2、 1.2.3 1.0、~ 1.2.3 ~ 2一律判为非法isValid返回false。这些边界由 测试用例表 完整覆盖其中1.2.3.4.5五段版本、1.2.3运算符与版本之间缺空格、!!1.2.3等输入都明确期望为非法。也就是说运算符与版本之间必须有空格这是从解析器「按空白分词」的实现方式决定的。预发布通道Prerelease Channels的匹配规则Paket 允许在约束尾部追加预发布通道标签如 1.2.3 alpha或~ 1.2 prerelease。其匹配语义可以归纳为三条稳定版本总是匹配只要数值区间满足稳定版本不受通道标签影响预发布版本需通道命中预发布版本只有在其通道名列于约束标签中、或约束使用了prerelease关键字时才匹配约束自身携带预发布版本则隐式放行该通道例如~ 1.2.3-alpha001会隐式允许alpha通道的版本无需再写alpha标签。实现上prereleaseChannel 负责从预发布后缀中提取通道名——对alpha001取前缀alpha对beta.2取首段betaprereleaseStatusOf 则把「显式标签」和「约束边界自带通道」归一为all即prerelease关键字、通道列表或none三种状态再由 matches 按区间类型逐一判定。此外还有一条容易踩坑的排序规则实现在 version.ts 的 compare 函数沿用 Paket 官方行为字面量prerelease后缀排序在同一个发布版本的所有其他预发布之下。因此1.2.3-prerelease实际上充当「所有1.2.3预发布的下界」。这一点在测试中有直接验证1.0.0-prerelease小于1.0.0-alphaisGreaterThan 测试而2.0.0-alpha1满足 2.0.0-prerelease 2.0.0 prerelease却不满足 2.0.0-prereleasematches 测试。解析策略前缀!与Paket 的 resolver strategy 前缀如!~ 1.2或 1.2.3表示依赖解析器的行为偏好。在 parseRange 中若输入以!或开头该字符被单独提取为PaketRange.strategy字段类型定义见 types.ts不改变哪些版本匹配而在 rangeToString 重新序列化时又会原样拼回前缀。这保证 Renovate 更新范围时前缀不会丢失对应测试!1.2.3更新到2.0.1得到!2.0.1 1.2.3得到 2.0.1getNewValue 测试表。pin策略下同样生效!~ 1.2钉住到1.5.0得到!1.5.0。范围重写replace保持约束形状Renovate 用replace策略替换范围时核心原则是保持约束的形状shape不变实现入口是 replaceRange 与 replaceConstraint。各运算符的逐条规则精确钉住保持精确钉住且保留原有运算符 1.2.3→ 2.0.1 1.2.3→ 2.0.1悲观约束按原精度平移~ 1.2更新到2.0.5得到~ 2.0保持两位精度~ 1.2.3更新到2.1得到~ 2.1.0保持三位精度。实现上通过 adaptToPrecision 把新版本截断/补齐到与旧约束相同的段数上界只上移恰好需要的距离 1.2.3 2.0更新到2.1.4得到 1.2.3 2.2。的上界用 bumpAtPrecision 在新版本精度上进一 2.0→ 2.6之于2.5.0而则直接取新版本本身 2.0→ 2.1.4~与 floor 的组合整体跟随~ 1.2 1.2.3更新到2.1.0时band 与 floor 数值一致floor 被判定为冗余而丢弃得到~ 2.1更新到2.1.3时得到~ 2.1 2.1.3。该逻辑集中在 pessimisticWithFloor预发布通道自动追加若新版本是预发布、且重写后的范围会挡住它则把其通道追加到范围尾部例如 1.2更新到2.0.0-beta1得到 1.2 beta。这一步由 ensurePrereleaseMatches 完成当通道名无法按标签规则表达时兜底追加字面量prerelease测试中2.5.0-0121的 1.0 2.6 prerelease即为此情形。两个重要护栏其一若新版本低于范围下界isLessThanLowerBound 判定getNewValue直接返回原值不改写其二若重写结果与原范围序列化后相同返回原字符串本身连多余空格都保留测试 1.0在newVersion: 1.0时原样返回即为验证verbatim 测试。bump 与 widen两种不同的下界/上界取舍除replace外Paket 模块还支持bump和widen策略两者的取舍点在 bumpRange 和 widenRange 中实现bump 策略把下界抬到精确的新版本语法允许时。例如~ 1.2更新到1.2.5得到~ 1.2 1.2.5——band 不动新增一个精确 floor。更多来自 测试表 的真实映射当前范围新版本bump 结果 1.01.5.0 1.5.0 1.01.5.0 1.5.0~ 1.21.2.5~ 1.2 1.2.5~ 1.22.1.3~ 2.1 2.1.3~ 1.2 1.2.31.2.5~ 1.2 1.2.5~ 1.2 1.91.5.3~ 1.5 1.9 1.0 2.02.5.0 2.5.0 2.6注意bump只处理「向上」的更新 1.0对1.0本身不做任何改写。widen 策略保持下界不变只扩展上界。最体现 widen 哲学的是悲观算子的分解~本身同时充当上下界无法单独放宽上界于是 widen 把它拆成显式的下界 上界——~ 1.2更新到2.1.0得到 1.2 3~ 1.2.3更新到1.4.1得到 1.2.3 1.5。若新版本仍在区间内如~ 1.2对1.1.0则原样返回。普通范围的 widen 则只动上界 1.0 2.0对2.1.0变为 1.0 2.2。与 NuGet 模块的差异对照最后用一个对照表把 Paket 与 NuGet 的关键分歧钉死避免配置时误用输入Paket 语义NuGet range 语义1.2.3精确钉住至少1.2.3即 1.2.3~ 1.2悲观约束 1.2 2不存在的运算符 1.2.3精确钉住且覆盖冲突无对应2.0.0-beta1vs 1.2.3不匹配无通道标签依 NuGet 预发布规则版本解析与比较层面两者共享同一套 NuGet 解析器1.2与1.2.0判等、1.2.3m1与1.2.3m2判等见 equals 测试分歧只在范围语法、通道匹配与范围重写这三层——这也是 Renovate 把paket做成独立 versioning 模块而非扩展 nuget 模块的根本原因。相关源码与测试入口模块 API 入口 lib/modules/versioning/paket/index.ts、约束解析与匹配 lib/modules/versioning/paket/range.ts、比较规则 lib/modules/versioning/paket/version.ts、类型定义 lib/modules/versioning/paket/types.ts、完整行为测试 lib/modules/versioning/paket/index.spec.ts以及模块说明文档 lib/modules/versioning/paket/readme.md。【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考