ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Renovate 自定义数据源(Custom Datasource)完全指南:用 HTTP(S) 通用端点驱动任意依赖的版本升级

Renovate 自定义数据源(Custom Datasource)完全指南:用 HTTP(S) 通用端点驱动任意依赖的版本升级 Renovate 自定义数据源Custom Datasource完全指南用 HTTP(S) 通用端点驱动任意依赖的版本升级【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate导读本文聚焦 Renovate 的custom数据源datasource讲解如何通过customDatasources配置项从任意 HTTP(S) 通用端点或本地file://文件获取版本数据从而让 Renovate 为那些没有现成数据源支持的软件自动升级依赖。你将掌握defaultRegistryUrlTemplate、format、transformTemplates三大核心参数的用法五种响应格式json/plain/yaml/toml/html的转换规则以及 K3s、Hashicorp、Grafana Dashboard、nginx 目录列表等真实场景的完整配置方案最终能独立为任意软件编写自定义数据源。一、认识 Custom DatasourceRenovate 的万能数据源Renovate 内置了大量数据源如 npm、maven、docker 等但在真实项目中总有一些依赖的版本信息来自非标准位置某个自建 API、一个简单的目录列表页面、甚至一个纯文本文件。custom数据源就是为这类场景设计的通用方案。在 lib/modules/datasource/custom/index.ts 中CustomDatasource被定义为static readonly id custom同时设置了customRegistrySupport true意味着它允许在依赖提取时通过registryUrl覆盖默认的 registry 地址。它的工作模式非常简单从配置中取出该数据源的defaultRegistryUrlTemplate、format与transformTemplates按format选择对应的 fetcherhtml/json/plain/toml/yaml发起 HTTP 请求或读取本地文件依次执行每条transformTemplates中的 JSONata 表达式前一条的输出作为后一条的输入用 Zod schema 校验最终结果通过后返回标准的ReleaseResult结构。整个流程在getReleases方法index.ts中清晰可见。配置解析逻辑则在 utils.ts 的getCustomConfig/massageCustomDatasourceConfig中datasource: custom.xxx中的custom.前缀会被剥离剩下部分作为customDatasources对象中的键名去查找对应配置。二、核心配置项与模板变量2.1 配置项速查表customDatasources是一个数据源名 - 配置对象的记录record其中每个数据源配置支持以下选项option默认值说明defaultRegistryUrlTemplate当查找新版本时未提供registryUrl时使用的 URL 模板formatjsonAPI 响应格式。可选值html、json、plain、toml、yamltransformTemplates[]用于转换 API 输出的 JSONata 规则 列表每条规则依次执行结果作为下一条的输入从 lib/config/types.ts 的CustomDatasourceConfig定义可以确认format的合法取值被限定为html、json、plain、toml、yaml五种且三个字段均为可选。2.2 模板变量在defaultRegistryUrlTemplate与transformTemplates中都可以使用 Handlebars 风格模板可用变量为packageName—— 当前依赖的包名currentValue—— 当前依赖版本值。模板编译发生在 utils.tstemplate.compile(registryUrlTemplate, templateInput)会在每次查找版本时将{ packageName, currentValue }注入模板。这意味着同一个自定义数据源可以通过 URL 模板为不同包服务例如 Hashicorp 示例中的https://api.releases.hashicorp.com/v1/releases/{{packageName}}?license_classoss。提示JSONata 表达式本身也可以用模板变量例如transformTemplates: [{{packageName}}]用于从多层嵌套的 JSON 中取出与包名对应的节点测试用例见 index.spec.ts。建议使用 JSONata Exerciser 在线调试你的规则。三、五种响应格式详解format决定 fetcher 如何解析 HTTP 响应体。fetcher 的注册表位于 formats/index.ts五种格式都实现了统一的fetch(http, registryURL)与readFile(registryURL)接口见 formats/types.ts因此它们既可以请求远程 URL也可以读取本地文件。3.1 JSON默认当format为json时响应体被直接解析为 JSON 并交给转换规则处理实现见 formats/json.ts。最理想的情况是 API 本身就返回 Renovate 的ReleaseResult结构此时无需任何转换即可直接使用测试用例见 index.spec.ts。3.2 Plain纯文本当format为plain时Renovate 会以Accept: text/plain头调用 HTTP 端点实现见 formats/plain.ts响应体被当作纯文本按换行分割、每行 trim 后作为一条版本1.0.0 2.0.0 3.0.0会被转换为{ releases: [ { version: 1.0.0 }, { version: 2.0.0 }, { version: 3.0.0 } ] }从源码看convertLinesToVersions对每行执行line.trim()因此带空白的行也能被正确解析对应测试见 index.spec.ts。转换完成后transformTemplates中的 JSONata 规则会照常继续处理。3.3 YAML当format为yaml时响应体通过parseSingleYaml解析并转换为 JSON 供后续处理实现见 formats/yaml.ts。例如releases: - version: 1.0.0 - version: 2.0.0 - version: 3.0.0会被转换为{ releases: [ { version: 1.0.0 }, { version: 2.0.0 }, { version: 3.0.0 } ] }之后同样应用transformTemplates中的 JSONata 规则。3.4 TOML当format为toml时响应体按 TOML 解析实现见 formats/toml.ts。下面的 TOML 文档[[releases]] version 1.0.0 [[releases]] version 2.0.0 [[releases]] version 3.0.0会被转换为{ releases: [ { version: 1.0.0 }, { version: 2.0.0 }, { version: 3.0.0 } ] }随后应用transformTemplates中的 JSONata 规则。3.5 HTML当format为html时Renovate 以Accept: text/html头调用端点将响应体作为 HTML 文档解析提取页面中所有a链接的href属性作为版本实现见 formats/html.ts。例如html body a hrefpackage-1.0.tar.gzpackage-1.0.tar.gz/a a hrefpackage-2.0.tar.gzpackage-2.0.tar.gz/a /body /html会生成{ releases: [ { version: package-1.0.tar.gz }, { version: package-1.0.tar.gz } ] }注意HtmlFetcher的extractLinks会特殊处理pre块——先解析pre内部的文本再提取其中的链接。这是为了兼容 nginx 等 Web 服务器把目录列表包裹在pre标签中的情况源码注释与测试用例均验证了这一点见 formats/html.ts 与 index.spec.ts。测试还覆盖了畸形 HTML 与不完整 HTML如a标签未闭合解析器均能容错处理。转换完成后JSONata 规则照常应用。由于提取到的是完整文件名如package-1.0.tar.gz而非纯净的版本号通常需要用extractVersion或 JSONata 规则进一步提取版本号。四、结果数据结构Renovate 期望的输出格式无论采用哪种格式、经过多少层转换最终结果都必须符合 Renovate 的ReleaseResult结构由 schema.ts 中的ReleaseResultZod校验。最小可用结构{ releases: [ { version: v1.1.0 }, { version: v1.2.0 } ] }全部可选字段{ releases: [ { version: v1.0.0, isDeprecated: true, releaseTimestamp: 2022-12-24T18:21Z, changelogUrl: https://github.com/demo-org/demo/blob/main/CHANGELOG.md#v0710, sourceUrl: https://github.com/demo-org/demo, sourceDirectory: monorepo/folder, digest: c667f758f9e46e1d8111698e8d3a181c0b10f430, isStable: true } ], sourceUrl: https://github.com/demo-org/demo, sourceDirectory: monorepo/folder, changelogUrl: https://github.com/demo-org/demo/blob/main/CHANGELOG.md, homepage: https://demo.org }各字段说明依据 schema.ts 的 Zod 定义字段层级说明versionreleases[] 必填版本号字符串必填isDeprecatedreleases[] 可选该版本是否已废弃releaseTimestampreleases[] 可选发布时间戳需符合MaybeTimestamp校验changelogUrlreleases[] 可选该版本对应的变更日志 URLsourceUrlreleases[] 可选源码仓库 URLsourceDirectoryreleases[] 可选源码仓库内子目录适用于 monorepodigestreleases[] 可选摘要值会被重命名为newDigest供后续使用isStablereleases[] 可选是否稳定版tags顶层可选标签到版本的映射如{latest: v1.0.0}sourceUrl/sourceDirectory/changelogUrl/homepage顶层可选整体仓库级元数据值得注意的细节schema 在解析时会执行transform把digest字段重命名为newDigestschema.ts因此数据源可以直接在releases中提供digest来支持 digest 型更新而CustomDatasource.getDigest方法默认返回null正是为了让 digest 由 getReleases 提供见 index.ts 及对应测试 index.spec.ts。另外schema 解析成功后会执行structuredClone(parsed)返回结果若校验失败则记录 debug 日志与 trace 日志并返回null不会抛出异常中断流程。五、端到端示例customDatasources regex 自定义管理器custom数据源通常与 regex 自定义管理器 配合使用regex manager 负责从文件中提取依赖声明custom datasource 负责查询版本。下面以更新k3s.version文件为例{ customManagers: [ { customType: regex, managerFilePatterns: [/k3s.version/], matchStrings: [(?currentValue\\S)], depNameTemplate: k3s, versioningTemplate: semver-coerced, datasourceTemplate: custom.k3s } ], customDatasources: { k3s: { defaultRegistryUrlTemplate: https://update.k3s.io/v1-release/channels, transformTemplates: [ {\releases\:[{\version\: $$.(data[id stable].latest),\sourceUrl\:\https://github.com/k3s-io/k3s\,\changelogUrl\:$join([\https://github.com/k3s-io/k3s/releases/tag/\,data[id stable].latest])}],\sourceUrl\: \https://github.com/k3s-io/k3s\,\homepage\: \https://k3s.io/\} ] } } }整个依赖查找链路为regex manager 从k3s.version文件匹配出currentValue→datasourceTemplate: custom.k3s指定数据源 →getCustomConfig剥离custom.前缀找到k3s配置 → 以json格式请求 K3s 频道 API → JSONata 从返回数据中取出stable频道的latest版本并拼接出changelogUrl→ 校验后返回releases数组。六、真实场景实战案例6.1 跟踪 K3s 最新稳定版单独使用customDatasources即可查询 K3s 最新稳定版与上节配合 regex manager 使用效果更佳{ customDatasources: { k3s: { defaultRegistryUrlTemplate: https://update.k3s.io/v1-release/channels, transformTemplates: [ {\releases\:[{\version\: $$.(data[id stable].latest),\sourceUrl\:\https://github.com/k3s-io/k3s\,\changelogUrl\:$join([\https://github.com/k3s-io/k3s/releases/tag/\,data[id stable].latest])}],\sourceUrl\: \https://github.com/k3s-io/k3s\,\homepage\: \https://k3s.io/\} ] } } }6.2 追踪 Hashicorp 产品线Nomad、Vault、Terraform 等Hashicorp 为所有产品提供了统一的 release API配合{{packageName}}模板变量即可用一份配置覆盖所有产品{ customManagers: [ { customType: regex, managerFilePatterns: [/\\.yml$/], datasourceTemplate: custom.hashicorp, matchStrings: [ #\\s*renovate:\\s*(datasource(?datasource.*?) )?depName(?depName.*?)( versioning(?versioning.*?))?\\s*\\w*:\\s*(?currentValue.*)\\s ], versioningTemplate: {{#if versioning}}{{{versioning}}}{{else}}semver{{/if}} } ], customDatasources: { hashicorp: { defaultRegistryUrlTemplate: https://api.releases.hashicorp.com/v1/releases/{{packageName}}?license_classoss, transformTemplates: [ { \releases\: $map($, function($v) { { \version\: $v.version, \releaseTimestamp\: $v.timestamp_created, \changelogUrl\: $v.url_changelog, \sourceUrl\: $v.url_source_repository } }), \homepage\: $[0].url_project_website, \sourceUrl\: $[0].url_source_repository } ] } } }要让 Ansible 变量文件中的 Nomad 版本保持最新在上述配置之外只需在 YAML 中加入 renvoate 注释指令# renovate: depNamenomad nomad_version: 1.6.0这里的{{packageName}}会被替换为nomad从而请求 Nomad 的 release API。6.3 升级 Grafana Helm chart 中的 DashboardGrafana Dashboard 的版本号存于 Helm chart 的values.yaml形如gnetIdrevision可通过自定义数据源查询 Grafana API{ customManagers: [ { customType: regex, managerFilePatterns: [/\\.yml$/], matchStrings: [ #\\srenovate:\\sdepName\(?depName.*)\\\n\\sgnetId:\\s(?packageName.*?)\\n\\srevision:\\s(?currentValue.*) ], versioningTemplate: regex:^(?major\\d)$, datasourceTemplate: custom.grafana-dashboards } ], customDatasources: { grafana-dashboards: { defaultRegistryUrlTemplate: https://grafana.com/api/dashboards/{{packageName}}, format: json, transformTemplates: [ {\releases\:[{\version\: $string(revision)}]} ] } } }Grafana Helm chartvalues.yaml中的对应片段dashboards: default: 1860-node-exporter-full: # renovate: depNameNode Exporter Full gnetId: 1860 revision: 31 datasource: Prometheus 15760-kubernetes-views-pods: # renovate: depNameKubernetes / Views / Pods gnetId: 15760 revision: 20 datasource: Prometheus这里的gnetId被提取为packageName用于构造请求 URLrevision被提取为currentValueJSONata 将 API 返回的revision转换为字符串版本号。6.4 无 API 时的替代方案自定义离线依赖文件有时依赖的版本来源根本没有可用 API。变通做法是自建版本追踪文件dependency files通过 HTTP(S) 暴露给 Renovate。例如为软件something准备versiontracker.json[ { version: 77 }, { version: 76 } ]再编写如下自定义数据源示例以 Nexus 作为 Web 服务器{ customDatasources: { nexus_generic: { defaultRegistryUrlTemplate: https://nexus.example.com/repository/versiontrackers/{{packageName}}/versiontracker.json, transformTemplates: [ { \releases\: $map($, function($v) { { \version\: $v.version, \sourceUrl\: $v.filelink } }) } ] } } }配合自定义管理器即可更新 Ansible YAML 中的版本号# renovate: datasourcecustom.nexus_generic depNamesomething versioningloose something_version: 77对应的 regex 自定义管理器{ customManagers: [ { customType: regex, managerFilePatterns: [/\\.yml$/], datasourceTemplate: custom.nexus_generic, matchStrings: [ #\\s*renovate:\\s*(datasource(?datasource.*?)\\s*)?depName(?depName.*?)(\\s*versioning(?versioning.*?))?\\s*\\w*:\\s*[\]?(?currentValue.?)[\]?\\s ], versioningTemplate: {{#if versioning}}{{{versioning}}}{{else}}semver{{/if}} } ] }如果不想搭建 HTTP 服务也可以把版本追踪文件放在本地仓库中用file://前缀指向相对路径{ customDatasources: { local_generic: { defaultRegistryUrlTemplate: file://dependencies/{{packageName}}/versiontracker.json, transformTemplates: [ { \releases\: $map($, function($v) { { \version\: $v.version, \sourceUrl\: $v.filelink } }) } ] } } }此时 Renovate 会从当前工作目录解析该文件。源码层面isLocalRegistry的判断逻辑是defaultRegistryUrlTemplate.startsWith(file://)命中后调用fetcher.readFile(...)读取本地文件见 index.ts五种格式均实现了readFile因此 json/plain/yaml/toml/html 全部支持本地文件模式对应测试见 index.spec.ts、index.spec.ts、index.spec.ts 与 index.spec.ts。6.5 解析 nginx 目录列表当只有一个装满文件的目录 能生成目录列表的 HTTP 服务器时html格式可以派上用场。以下配置跟踪 nginx 官方下载目录{ customDatasources: { nginx: { defaultRegistryUrlTemplate: https://nginx.org/download, format: html } }, packageRules: [ { matchDatasources: [custom.nginx], extractVersion: ^nginx-(?version.)\\.tar\\.gz$ } ] }由于html格式提取到的是完整文件名必须用extractVersion正则从中提取纯版本号。6.6 解析普通 HTML Downloads 页面同理html格式也可以用于典型的下载页面例如 curl 官网{ customDatasources: { curl: { defaultRegistryUrlTemplate: https://curl.se/download.html, format: html } }, packageRules: [ { matchDatasources: [custom.curl], extractVersion: /curl-(?version.)\\.tar\\.gz$ } ] }注意extractVersion既支持字符串正则也支持/.../包裹的正则字面量写法。七、故障排查与日志调试7.1 内置的追踪日志Renovate 在转换之前会写入 trace 级日志Custom datasource API fetcher ${format} received data. Starting transformation.如果发现意外的数据格式还会在转换之后额外写一条 trace 日志。这意味着LOG_LEVELtrace时你可以在日志中同时看到转换前后的原始数据与结果数据见 index.ts 与 index.ts。调试经验JSONata 表达式编译失败时会以logger.once.warn输出Invalid JSONata expression如$[.name Alice and这类语法错误测试见 index.spec.tsJSONata 表达式执行抛错时会输出Error while evaluating JSONata expression测试见 index.spec.ts结果未通过 schema 校验时会输出 debug 级Response has failed validation与 trace 级的数据快照然后返回null未找到对应自定义数据源、未提供 registry URL、HTTP 请求失败等场景均返回null并伴随对应日志测试覆盖见 index.spec.ts。7.2 在 Mend 托管 App 上获取 trace 日志如果使用 Mend Renovate 托管应用可通过logLevelRemap配置项把特定消息提升到 info 级别输出{ logLevelRemap: [ { matchMessage: /^Custom datasource/, newLogLevel: info } ] }7.3 自托管时获取 trace 日志自托管 Renovate 时按以下步骤开启 trace 日志设置环境变量LOG_FILE_LEVEL为trace以dryRun模式运行 Renovate避免实际创建 PR安全观察数据源返回的版本数据。八、最佳实践小结优先复用内置数据源custom数据源适用于内置数据源无法覆盖的通用 HTTP(S) 端点场景不要用它重复造轮子。模板变量让一份配置服务多个包善用{{packageName}}与{{currentValue}}构造 URL 和转换规则如 Hashicorp、Grafana 示例。JSONata 转换保持链式、幂等多条transformTemplates依次执行、层层递进建议先在 JSONata Exerciser 中验证表达式再写入配置。让 API 直接输出 Renovate 格式若 API 归你控制直接返回{releases: [...]}结构可省去全部转换逻辑测试验证了直接暴露 Renovate 格式的场景见 index.spec.ts。结合extractVersion清洗版本html/plain等格式提取到的常是文件名或整行文本用extractVersion或 JSONata 提取纯净版本号。注意 schema 校验的严格性version是releases中唯一必填字段其余均为可选非法数据不会导致任务失败而是静默返回null并记录日志调试时务必开启 trace 级日志。九、延伸阅读Custom Datasource 源码 与 配置解析结果结构校验 schema 与 五种格式 fetcher单元测试含全部格式与异常路径regex 自定义管理器extractVersion配置说明logLevelRemap配置说明自托管配置中的dryRun【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表