Renovate 的 deps.edn 管理器:Clojure deps.edn 依赖提取原理与实战

Renovate 的 deps.edn 管理器:Clojure deps.edn 依赖提取原理与实战 Renovate 的 deps.edn 管理器Clojure deps.edn 依赖提取原理与实战【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate本篇文章聚焦 Renovate 项目中lib/modules/manager/deps-edn这一包管理器模块深入讲解它是如何从 Clojure 生态的deps.edn以及 Babashka 的bb.edn文件中提取 Maven 依赖、Git 依赖并生成升级建议的。读完本文你将掌握 Renovate 识别该文件类型的匹配规则、内置 EDN 解析器的实现思路、mvn/repos自定义仓库的解析方式以及mvn/version、git/url、git/tag、git/sha等声明形式对应的提取与数据源映射关系。一、deps.edn 管理器概述在 Renovate 中每个包管理器manager负责识别一类依赖清单文件并提取其中的依赖项。deps-edn管理器正是为 Clojure 的依赖描述文件而生。其 readme 只有一句核心定位Extracts Maven dependencies fromdeps.ednfiles.即从deps.edn文件中提取 Maven 依赖。而结合 index.ts 的源码可以看到该管理器的实际能力比这句话更丰富——它不只处理 Clojars / Maven Central 的库依赖还支持以 Git 仓库形式声明的依赖通过git/url、git/tag、git/sha并且可以识别 GitHub、GitLab、Bitbucket 的命名空间约定。管理器的基本注册信息见 index.ts配置项值说明displayNamedeps.edn管理器显示名称urlhttps://clojure.org/reference/deps_edn指向 Clojure 官方 deps.edn 规范categories[java]归入 Java 生态分类managerFilePatterns/(^|/)(?:deps|bb)\.edn$/匹配deps.edn与bb.edn文件versioningmaven默认使用 Maven 版本语义supportedDatasources[clojure]支持 Clojure 数据源该管理器导出extractPackageFile作为提取入口见 index.ts数据源为clojure底层由ClojureDatasource实现它继承自 MavenDatasource见 clojure/index.ts默认注册表为 Clojars 与 Maven Central。二、文件匹配规则与适用场景deps.edn是 Clojure CLItools.deps的依赖配置文件通常位于项目根目录bb.edn则是 Babashka 的配置文件同样使用 EDN 格式声明依赖。管理器的默认managerFilePatterns正则/(^|/)(?:deps|bb)\.edn$/它要求文件名为deps.edn或bb.edn可位于仓库根目录或任意子目录(^|/)允许路径分隔符前导。因此无论 Clojure 项目将依赖文件放在根目录还是嵌套目录中Renovate 都能自动识别。由于该文件类型结构固定、无 lockfile 参与版本锁定Renovate 会直接读取deps.edn中声明的版本并结合 Maven 版本规则mavenversioning与 Clojure 数据源查询最新版本进而创建更新 PR。三、内置 EDN 解析器不依赖外部库的自研实现与许多使用现成解析库的 manager 不同deps-edn在 parser.ts 中内置了一套 EDN 解析器底层采用moo词法分析器按状态机分多个 lexer 状态进行词法分析然后通过显式的栈式解析器parser stack构建出树形结构。3.1 词法规则lexer statesparser.ts中定义的lexerStates覆盖了 EDN 的主要语法元素见 parser.ts分隔符与括号,、(、)、[、]、{、}行注释;开头直到行尾/;.*?$/字符串普通双引号...与三引号长字符串...分状态处理关键字keyword:开头如:deps、:mvn/version解析时去掉前导冒号符号symbol普通标识符如org.clojure/clojure数值double含科学计数法、rational分数1/2、integer含十六进制0x与其他进制Nr形式。其中关键字与符号的正则都允许/分隔符这正是为了支持org.clojure/clojure这类带命名空间的依赖名见 parser.ts。3.2 栈式解析与元数据词法 token 流随后进入一个显式栈解析循环见 parser.ts遇到(、[、{时压栈并进入对应的 array / record 状态遇到右括号时弹出栈帧并收拢数据。解析器最终要求顶层是一个 mapisPlainObject(state.data)否则返回null见 parser.ts。值得一提的设计是元数据保留在关闭 record / array 时解析器会把该结构在原文中的原始文本片段replaceString通过WeakMap记录下来见 parser.ts。从 types.ts 可以看到EdnMetadata只保存replaceString字段这为后续的依赖替换如精确重写版本字符串保留了原文依据。3.3 解析器的测试覆盖parser.spec.ts 用表格驱动的方式覆盖了大量边界输入空字符串、裸关键字/符号/数字、空 map、嵌套 map/vector、{:foo :bar}与{:foo foo}等多种组合并验证了metadata中replaceString的取值如{:mvn/version,0.1.2}。这些用例可以直接作为理解解析器行为的参考。四、依赖提取流程从:deps到更新候选提取入口extractPackageFile见 extract.ts的整体流程如下调用parseDepsEdnFile解析文件解析失败则返回null视为不支持的文件读取:mvn/repos段构建 Maven 注册表列表从:deps段提取直接依赖遍历:aliases段从每个 alias 的:extra-deps与:override-deps中继续提取依赖并把 alias 名作为depType。4.1:deps直接依赖典型写法参见fixtures/deps.edn{ :deps { org.clojure/clojure {:mvn/version 1.11.1} io.github.nextjournal/clerk {:mvn/version 0.7.418} } }extractDependency见 extract.ts会先对依赖键名做合法性校验dependencyRegex要求键形如groupId或groupId/artifactId其中 groupId / artifactId 只能由字母、数字、-、_、.组成见 extract.ts。随后将groupId:artifactId作为最终的packageName见 extract.ts。4.2 提取结果字段每个依赖对象包含如下字段源码见 extract.ts字段来源含义depName依赖键原样如org.clojure/clojurepackageNamegroupId:artifactId或 Git 包名用于查询数据源currentValue:mvn/version或:git/tag当前版本currentDigest:git/sha或:sha当前提交摘要取前 7 位作为currentDigestShortdatasource由声明形式推断clojure或github-tags/gitlab-tags/bitbucket-tags/git-refsregistryUrls:mvn/repos合并结果查询时使用的仓库列表depTypealias 名如dev、test、repl五、两类依赖的判定逻辑5.1 Maven / Clojars 依赖:mvn/version当依赖值为一个 map 且包含:mvn/version时见 extract.tsdatasource设为clojurecurrentValue取:mvn/version字符串packageName中的/替换为:如org.clojure/clojure→org.clojure:clojure与 Maven 坐标groupId:artifactId对齐registryUrls复制当前解析出的 Maven 注册表。Clojure 数据源继承 MavenDatasource采用registryStrategy merge策略默认注册表为 Clojarshttps://clojars.org/repo与 Maven Centralhttps://repo.maven.apache.org/maven2见 clojure/index.ts 与 clojure/common.ts、maven/common.ts。5.2 Git 依赖:git/url、:git/tag、:git/shadeps.edn允许直接引用 Git 仓库作为依赖。提取器分两条路径解析路径一按值解析:git/url。resolveGitPackageFromEdnVal见 extract.ts用三个正则分别匹配 GitHub、GitLab、Bitbucket 的 HTTPS 或 SSH 地址# GitHub ^(?:https:\/\/|git)github\.com/:(?:\.git)?$命中后设置对应数据源github-tags/gitlab-tags/bitbucket-tags与sourceUrl。若 URL 不属于这三家托管平台如gitexample.com/foo.git则回退为git-refs数据源packageName直接取完整 URL并去掉末尾.git作为sourceUrl。路径二按键名解析命名空间约定。resolveGitPackageFromEdnKey见 extract.ts识别形如io.github.owner/repo、com.gitlab.owner/repo、org.bitbucket.owner/repo的依赖键分别映射到对应托管平台的 tags 数据源。这也是 Clojure 社区中常见的 Git 依赖命名惯例。提取结果中:git/tag作为currentValue见 extract.ts:git/sha或:sha作为currentDigest前 7 位写入currentDigestShort见 extract.ts。若既无:mvn/version也无法识别 Git 来源例如空 mapbaz/baz {}则该依赖被丢弃返回null。六、:mvn/repos自定义仓库解析Clojure CLI 允许通过:mvn/repos修改默认仓库列表Renovate 完整支持这一特性源码见 extract.ts。解析逻辑如下初始化默认注册表clojars→https://clojars.org/repocentral→https://repo.maven.apache.org/maven2遍历:mvn/repos中的每一项map 形式{:url ...}用自定义 URL 覆盖同名默认仓库或新增仓库值为nil的字符串形式删除同名仓库即禁用默认仓库。示例来自fixtures/deps.edn:mvn/repos { my-auth-repo {:url https://my.auth.com/repo} central nil ; 禁用 Maven Central my-private-repo {:url s3://my-bucket/maven/releases} clojars {:url https://deps.com/foo/bar} ; 覆盖默认 Clojars }解析后mavenRegistries依次为https://deps.com/foo/bar、https://my.auth.com/repo、s3://my-bucket/maven/releases——这正是 extract.spec.ts 中断言的结果。注意仓库顺序由 map 遍历顺序决定且 S3 等自定义协议 URL 会被原样保留在注册表列表中。七、:aliases段的额外依赖与覆盖依赖deps.edn的:aliases段可以按使用场景开发、测试、REPL 等声明额外的依赖。提取器遍历每个 alias见 extract.ts:extra-depsalias 额外引入的依赖:override-deps覆盖默认版本的依赖。两者都会走与:deps相同的extractDependency逻辑且 alias 名会写入depType。例如 fixture 中:testalias 下的 Git 依赖会得到depType: test参见 extract.spec.ts 中对test-gitlab、test-bitbucket的断言。值得注意即便同一个依赖在多个 alias 中重复出现如org.clojure/clojurescript同时出现在:dev与:test提取器也会全部保留为独立依赖记录便于按场景分别跟踪升级。八、端到端验证fixture 与测试仓库提供了完整的 fixture 与单元测试可作为行为规格说明fixture 文件fixtures/deps.edn 覆盖了:deps、多个:aliases含:extra-deps、:override-deps、:extra-paths、:main-opts、:mvn/repos覆盖与禁用、GitHub/GitLab/Bitbucket/自建 Git 地址等场景extract.spec.ts 验证了 19 条依赖记录的提取结果包括registryUrls的合并顺序、depType的注入、git-refs回退与sourceUrl生成非法输入如纯数字内容返回nullparser.spec.ts 验证了解析器对 EDN 各类字面量与嵌套结构的处理以及replaceString元数据的准确性。若想在本仓库中快速验证提取行为可直接阅读上述测试用例或在本地运行对应的测试文件。九、适用前提与注意事项仅识别deps.edn与bb.edn其他 EDN 文件如shadow-cljs.edn不在默认匹配范围内如需支持可自行在 Renovate 配置中调整managerFilePatterns相关规则版本语义为 Mavendeps-edn默认使用mavenversioning见 index.ts因此版本比较遵循 Maven 规则与 Clojure 生态的坐标体系一致非法键名会被忽略包含非法字符的依赖键如invalid/package!无法通过dependencyRegex不会生成依赖记录无:mvn/version且无法识别 Git 来源的声明会被丢弃如空 map 依赖git-refs数据源用于非主流托管平台GitHub / GitLab / Bitbucket 之外的git/url会被视为git-refs通过 Git 引用查询版本此时需要仓库可访问。综上Renovate 的deps-edn管理器以约两百行核心实现完整覆盖了 Clojure 依赖配置的主流声明形态从文件匹配、EDN 解析、依赖分类到 Maven 仓库合并与 Git 托管平台识别是理解 Renovate 如何为小众生态提供依赖自动化能力的典型范例。相关源码均可从 lib/modules/manager/deps-edn 目录下直接查阅。【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考