Renovate 的 Terraform 管理器:.tf配置文件中的依赖如何被自动识别与更新
【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate
本篇基于 Renovate 仓库中 Terraform 管理器文档 展开,讲解该管理器覆盖哪些 Terraform 资源(模块、Provider、Terraform 版本、Helm、Docker、Kubernetes 等)、每种依赖对应的depType、支持的版本约束语法,以及如何用packageRules将默认注册表从 Terraform Registry 切换为 OpenTofu Registry;并结合 extract.ts、base.ts 等源码,说明「预检 → HCL 解析 → 分类抽取」的完整提取链路。读完你可以掌握:为 Terraform 仓库配置 Renovate 时的全部开关项,以及判断某个module/provider来源是否会被更新的依据。
管理器总览:识别哪些文件、对接哪些数据源
Renovate 的 Terraform 管理器定义在 lib/modules/manager/terraform/index.ts 中。默认配置如下(defaultConfig):
{ "commitMessageTopic": "Terraform {{depName}}", "managerFilePatterns": ["**/*.tf", "**/*.tofu"], "pinDigests": false }由此可知三件事:
- 扫描范围默认匹配所有
*.tf与*.tofu文件(OpenTofu 的文件扩展名同样在扫描范围内); - 提交信息主题默认为
Terraform <depName>; - 默认不固定 digest(
pinDigests: false)。
同一文件中还声明了管理器支持的 8 个数据源(supportedDatasources):bitbucket-tags、docker、git-tags、github-releases、github-tags、helm、terraform-module、terraform-provider,并声明了锁文件支持:
export const supportsLockFileMaintenance = true; export const lockFileNames = ['.terraform.lock.hcl'];即管理器理解 Terraform 的锁文件.terraform.lock.hcl,并支持锁文件维护(lockfile maintenance)。
提取链路:预检、HCL 解析与抽取器
整个提取入口是 extract.ts 中的extractPackageFile,其流程与文档中「支持的依赖」清单一一对应:
- 预检(preflight content check):遍历 extractors.ts 注册的 7 个抽取器(
HelmReleaseExtractor、GenericDockerImageRefExtractor、TerraformWorkspaceExtractor、RequiredProviderExtractor、TerraformVersionExtractor、ProvidersExtractor、ModuleExtractor),每个抽取器通过getCheckList()给出关键词(如'module'、'provider'、'required_version'、'required_providers')。只要文件内容包含任一关键词,对应抽取器才会参与解析——这一步在 util.ts 的checkFileContainsDependency中实现(简单的content.includes(check)),避免对无关文件做昂贵的 HCL 解析。 - HCL 解析:通过 hcl/index.ts 调用
@cdktf/hcl2json把 HCL 文本解析为 JSON 形式的 AST(TerraformDefinitionFile);解析失败(语法错误)时直接返回null,该文件被跳过。 - 锁文件关联:
extractLocksForPackageFile从同目录的.terraform.lock.hcl中提取已锁定的 provider 版本,供后续确定注册表与lockedVersion使用。 - 分类抽取:每个通过的抽取器调用
extract(hclMap, locks, config)产出PackageDependency列表,最终统一返回。
这个「先按关键词预筛、再按块类型分派」的设计,正是下面各依赖类型能够独立开关的原因——每个抽取器对应一组depType。
支持的依赖类型总览
以下表格完整继承自 readme.md,列出各类依赖及其可托管位置(公开/私有):
模块(Modules)
| Name | Public hosting | Private hosting |
|---|---|---|
| GitTags | yes | yes |
| GithubTags | yes | yes |
| TerraformRegistry | yes | yes |
Provider(provider块)
Providers 在 Terraform0.13.0起被废弃(新代码应使用required_providers块),Renovate 仍然兼容旧写法:
| Name | Public hosting | Private hosting |
|---|---|---|
| TerraformRegistry | yes | yes |
required_providers块
要求 Terraform>= 0.13.0:
| Name | Public hosting | Private hosting |
|---|---|---|
| TerraformRegistry | yes | yes |
required_version
Renovate 可以更新terraform块中的required_version属性。从 terraform-version.ts 的实现看,其依赖信息固定为:
dep.depType = 'required_version'; dep.datasource = GithubReleasesDatasource.id; // 通过 GitHub Releases 查询 dep.depName = 'hashicorp/terraform'; dep.extractVersion = 'v(?<version>.*)$'; // 剥离 release tag 的 v 前缀 dep.versioning = hashicorp.id; // 使用 hashicorp 版本规则即 Terraform 本体版本通过hashicorp/terraform的 GitHub Releases 获取,并使用 hashicorp 版本规则 比较版本(该规则能处理 HashiCorp 产品特有的版本格式,如1.5.7、1.6.0-beta1等)。
helm_release资源
Renovate 可以更新helm_release资源的version属性,同时支持 Helm chart 仓库和发布在 OCI 注册表中的 chart。
| Name | Public hosting | Private hosting |
|---|---|---|
| chart repository | yes | yes |
Docker 镜像
可以更新 Docker provider 资源(docker_*)中的镜像引用:
| Name | Public hosting | Private hosting |
|---|---|---|
| Docker registry | yes | yes |
Kubernetes 工作负载
可以更新 Kubernetes provider 资源(kubernetes_*)中的镜像引用:
| Name | Public hosting | Private hosting |
|---|---|---|
| Docker registry | yes | yes |
tfe_workspaces
Renovate 可以更新tfe_workspaces资源中的terraform_version参数。
模块来源的识别规则(源码级)
模块抽取的核心在 extractors/others/modules.ts。文件内容中的module块被取出后,analyseTerraformModule按以下优先级解析source:
| 来源形式 | 示例(取自fixtures/modules.tf) | 数据源 / 处理 |
|---|---|---|
| OCI 注册表 | source = "registry.example.com/namespace/repo?tag=1.0.0" | 走applyOciDependency,按 docker 镜像引用解析 |
| GitHub | source = "github.com/hashicorp/example?ref=v1.0.0"、git@github.com:hashicorp/example.git?ref=v2.0.0 | 使用github-tags数据源,按?ref=指定的 tag 匹配;支持子目录(//terraform/modules/...)与.git后缀剥离 |
| Bitbucket | source = "bitbucket.org/workspace/project.git?ref=v1.0.0" | 使用bitbucket-tags数据源 |
| 通用 Git 仓库(含 Azure DevOps SSH) | source = "git@git.example.com:group/repo/foo?depth=1&ref=v1.0.0" | 使用git-tags数据源,可携带depth参数与子目录 |
| Terraform 注册表 | source = "hashicorp/consul/aws"、source = "app.terraform.io/example-corp/k8s-cluster/azurerm" | 使用terraform-module数据源;若来源形如hostname/namespace/type/...(如app.terraform.io),会把https://<hostname>写入registryUrls以支持私有模块注册表 |
两种情况会被跳过:
- 相对路径模块(
source = "./relative"、source = "../../modules/fe")→skipReason = 'local',本地模块没有远端版本可言; - 没有
source属性的module块 →skipReason = 'no-source'。
测试夹具fixtures/modules.tf 覆盖了大量边界样例:带depth=1的 git 引用、带点的仓库名(example.2.3)、?ref=next之类的非语义化 tag、私有注册表域名(app.terraform.io)等,可对照 extract.spec.ts 查看预期抽取结果。
Provider 的注册表推断逻辑(源码级)
provider块与required_providers块共用抽象基类 base.ts 中的TerraformProviderExtractor.analyzeTerraformProvider(约 L39–L101),其推断顺序为:
- OCI 来源:若
source是 OCI 注册表地址,按 docker 镜像依赖处理; - 正则拆解 source:
sourceExtractionRegex把来源拆成hostname/namespace/type三段。解析失败则skipReason = 'unsupported-url'; - 内置 Provider:
namespace === 'terraform-providers'(如terraform-providers/docker)的旧式来源,直接指向 HashiCorp 的 release URL(hashicorpReleaseUrl); - 显式域名:来源带 hostname(如
terraform.example.com/hashicorp/kubernetes、terraform-company_special.example.com/oracle/oci)时,registryUrls = ['https://<hostname>'],packageName = '<namespace>/<type>'——这是私有 provider 注册表的关键路径; - 默认注册表 + 锁文件辅助:没有 hostname 时(如
source = "aws"或完全省略 source 用块名回退),从.terraform.lock.hcl中查找同名 lock;若恰好唯一且其registryUrl不是默认的registry.terraform.io,则采用该 lock 的注册表。从源码结构看,这是 Renovate 在「未显式声明注册表」时仍能更新私有 provider 的兜底机制; - 名称规整:util.ts 的
massageProviderLookupName会把不含/的 provider 名补成hashicorp/<name>并整体转小写(例如Telmate/proxmox会规整为telmate/proxmox),因为 Terraform 注册表的 provider 标识不区分大小写; - 锁定版本:
getLockedVersion按packageName + registryUrl精确匹配 lock,产出lockedVersion,用于判断是否需要更新以及写回锁文件。
required_providers的两种写法(见 required-provider.ts)都会被处理:
# 简写:aws = ">= 2.7.0" # 块式:aws = { source = "aws", version = "2.7.0" } # source 省略时用块名回退夹具fixtures/providers.tf 展示了完整场景:简写约束、=精确版本、私有注册表(terraform.example.com、terraform-company_special.example.com)、terraform-providers/旧前缀、非法 source(//hashicorp/helm,会被标记unsupported-url)以及required_version = ">= 0.13"等。
版本约束(Range constraints)
Renovate 理解以下 Terraform 版本约束(与原文档表格一致):
| Terraform range | 含义 |
|---|---|
>= 1.2.0 | 版本1.2.0或更新 |
<= 1.2.0 | 版本1.2.0或更旧 |
~> 1.2.0 | 非 beta 的>= 1.2.0且< 1.3.0,即1.2.X |
~> 1.2 | 非 beta 的>= 1.2.0且< 2.0.0,即1.X.Y |
>= 1.0.0, <= 2.0.0 | 1.0.0到2.0.0(含两端)之间的任意版本 |
这些约束的解析由 Terraform 依赖默认使用的 hashicorp 版本规则完成(见 lib/modules/versioning/hashicorp)。如果需要整体更换版本规则,可按原文档指引阅读仓库中的 versioning 模块文档后,在配置里覆盖versioning选项。
关闭或裁剪管理器的某些部分(depType 一览)
原文档提供了用depType做细粒度控制的完整清单。以下表格完整继承,depType与 dep-types.ts 中knownDepTypes的定义一一对应:
| Resource | depType | Notes |
|---|---|---|
| Terraform provider | provider | |
| required Terraform provider | required_provider | |
| required Terraform version | required_version | This handles therequired_versionin terraform blocks |
| TFE workspace | tfe_workspace | This handles theterraform_versionargument intfe_workspaceresources |
| Terraform module | module | |
| Helm release | helm_release | |
| Docker container | docker_container | |
| Docker image | docker_image | |
| Docker service | docker_service | |
| Kubernetes CronJob | kubernetes_cron_job | |
| Kubernetes CronJob v1 | kubernetes_cron_job_v1 | |
| Kubernetes DaemonSet | kubernetes_daemon_set | |
| Kubernetes DaemonSet v1 | kubernetes_daemon_set_v1 | |
| Kubernetes Deployment | kubernetes_deployment | |
| Kubernetes Deployment v1 | kubernetes_deployment_v1 | |
| Kubernetes Job | kubernetes_job | |
| Kubernetes Job v1 | kubernetes_job_v1 | |
| Kubernetes Pod | kubernetes_pod | |
| Kubernetes Pod v1 | kubernetes_pod_v1 | |
| Kubernetes Replication Controller | kubernetes_replication_controller | |
| Kubernetes Replication Controller v1 | kubernetes_replication_controller_v1 | |
| Kubernetes StatefulSet | kubernetes_stateful_set | |
| Kubernetes StatefulSet v1 | kubernetes_stateful_set_v1 |
Data Source 部分:
| Data Source | depType |
|---|---|
| Docker registry image | docker_registry_image |
例如,只想更新模块而暂停 provider 更新,可以这样写:
{ "packageRules": [ { "matchManagers": ["terraform"], "matchDepTypes": ["provider", "required_provider"], "enabled": false } ] }Kubernetes 相关depType之所以区分v1与非v1,是因为kubernetes_pod等是 K8s provider 的旧资源名,kubernetes_pod_v1是 K8s API 迁移到v1group 后的新资源名,两者的更新可以独立控制。
Terraform 与 OpenTofu:注册表选择的覆盖方式
原文档指出:Renovate 无法自动判断你要使用 Terraform Registry 还是 OpenTofu Registry。对于没有显式注册表定义的 provider 和模块,默认使用 Terraform Registry(registry.terraform.io)。这与源码一致:required_providers无 hostname 且锁文件也无其他注册表时,查询走默认注册表(见上文第 5 点及 util.ts 中getLockedVersion对defaultRegistryUrls的回退)。
要默认改走 OpenTofu 的注册表,可用packageRules覆盖:
{ "packageRules": [ { "matchDatasources": ["terraform-provider", "terraform-module"], "registryUrls": ["https://registry.opentofu.org"] } ] }注意适用范围:该规则作用于两个 Terraform 数据源;如果某个source已经写了显式 hostname(如terraform.example.com/...)或来源来自 OCI 注册表,则其registryUrls由来源本身决定,优先级高于此默认覆盖。
锁文件与验证材料
- 锁文件读取与 lock 提取实现位于 lockfile/util.ts,锁文件更新实现位于 lockfile/update-locked.ts,与
index.ts中导出的updateArtifacts/updateLockedDependency对应。 - 提取行为的自动化验证集中在 extract.spec.ts 及各抽取器目录下的
*.spec.ts(如 extractors/others/modules.spec.ts),夹具文件(__fixtures__/下的modules.tf、providers.tf、terraformBlock.tf、helm.tf、docker.tf、kubernetes.tf、tfeWorkspace.tf等)覆盖了上文提到的各类来源写法与约束格式,适合作为「我的写法是否会被识别」的参照样例。
小结
Renovate 的 Terraform 管理器把*.tf/*.tofu文件中的六类更新目标——模块、provider(新旧两种块)、Terraform 自身版本、Helm release、Docker 镜像、Kubernetes 工作负载镜像与 TFE 工作空间版本——统一纳入「关键词预检 → HCL 解析 → 分抽取器处理 → 注册表/锁文件推断」的流水线。配置侧的抓手主要有三个:depType(开关粒度)、registryUrls(注册表选择,含 OpenTofu 覆盖)、versioning(约束解析规则)。判断某个具体写法能否被更新时,最可靠的方式是对照 extract.spec.ts 与__fixtures__/下的夹具确认是否存在同类用例。
【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考