UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

122 lines (121 loc) 6.01 kB
import { logger } from "../../../logger/index.js"; import { getQueryString, isHttpUrl, joinUrlParts } from "../../../util/url.js"; import { id } from "../../versioning/hashicorp/index.js"; import { withCache } from "../../../util/cache/package/with-cache.js"; import { OpenTofuModuleDocsResponse, ProtocolModuleResponse, TerraformModuleResponse, TerraformModuleV2Response } from "./schema.js"; import { TerraformDatasource } from "./base.js"; import { createSDBackendURL, getRegistryRepository } from "./utils.js"; //#region lib/modules/datasource/terraform-module/index.ts var TerraformModuleDatasource = class TerraformModuleDatasource extends TerraformDatasource { static id = "terraform-module"; static terraformCloudUrl = "https://app.terraform.io"; static defaultRegistryUrls = [TerraformModuleDatasource.terraformRegistryUrl]; constructor() { super(TerraformModuleDatasource.id); } defaultRegistryUrls = TerraformModuleDatasource.defaultRegistryUrls; defaultVersioning = id; releaseTimestampSupport = true; releaseTimestampNote = "For `registry.terraform.io` and `registry.opentofu.org` (via `api.opentofu.org`), release timestamps are available for all versions. For `app.terraform.io`, only the latest version is annotated, using the `published_at` field from the extended module endpoint."; sourceUrlSupport = "package"; sourceUrlNote = "For `registry.terraform.io` and `app.terraform.io`, the source URL is taken from the `source` field of the registry response. For `registry.opentofu.org`, it is derived from the package name following the OpenTofu registry policy of `github.com/NAMESPACE/terraform-TARGETSYSTEM-NAME`."; /** * Resolves a module release list for the configured registry. * * Requests against the public Terraform registry and Terraform Cloud use the * registry-specific module endpoint, while other registries use the generic * Module Registry Protocol versions endpoint. */ async _getReleases({ packageName, registryUrl }) { /* v8 ignore next 3 -- should never happen */ if (!registryUrl) return null; const { registry, repository } = getRegistryRepository(packageName, registryUrl); logger.trace({ registryUrlNormalized: registry, terraformRepository: repository }, "terraform-module.getReleases()"); try { if (registry === TerraformModuleDatasource.terraformRegistryUrl) return await this.queryTerraformRegistryV2(registry, repository); if (registry === TerraformModuleDatasource.openTofuRegistryUrl || registry === TerraformModuleDatasource.openTofuApiUrl) return await this.queryOpenTofuRegistry(repository); if (registry === TerraformModuleDatasource.terraformCloudUrl) return await this.queryTerraformRegistry(registry, repository); return await this.queryModuleRegistry(registry, repository); } catch (err) { this.handleGenericErrors(err); } } getReleases(config) { return withCache({ namespace: `datasource-${TerraformModuleDatasource.id}`, key: TerraformModuleDatasource.getCacheKey(config), fallback: true }, () => this._getReleases(config)); } /** * Query the Terraform Registry using the undocumented v2 JSON:API. * * Returns release timestamps for all versions, unlike the v1 extended * module endpoint which only exposed the timestamp for the latest version. */ async queryTerraformRegistryV2(registryUrl, repository) { const moduleUrl = `${joinUrlParts(registryUrl, "v2/modules", repository)}?${getQueryString({ include: "module-versions" })}`; const { body: res } = await this.http.getJson(moduleUrl, TerraformModuleV2Response); res.homepage = `${registryUrl}/modules/${repository}`; return res; } /** * Query the OpenTofu registry docs API. * https://api.opentofu.org/ * * Used when the registry URL is `registry.opentofu.org`. * Queries `api.opentofu.org` for module versions with release timestamps. */ async queryOpenTofuRegistry(repository) { const docsUrl = joinUrlParts(TerraformModuleDatasource.openTofuApiUrl, "registry/docs/modules", repository, "index.json"); const { body: res } = await this.http.getJson(docsUrl, OpenTofuModuleDocsResponse); res.homepage = `https://search.opentofu.org/module/${repository}`; const [namespace, name, target] = repository.split("/"); res.sourceUrl = `https://github.com/${namespace}/terraform-${target}-${name}`; return res; } /** * Queries the Terraform Registry module endpoint. * * The response includes the latest published version separately, so only that * release can be annotated with `releaseTimestamp`. * * https://developer.hashicorp.com/terraform/registry/api-docs#get-a-specific-module */ async queryTerraformRegistry(registryUrl, repository) { const pkgUrl = createSDBackendURL(registryUrl, "modules.v1", await this.getTerraformServiceDiscoveryResult(registryUrl), repository); const { body: res } = await this.http.getJson(pkgUrl, TerraformModuleResponse); return { releases: res.versions, sourceUrl: res.source, homepage: `${registryUrl}/modules/${repository}` }; } /** * Queries a registry through the Terraform Module Registry Protocol. * * This is the default path for registries implementing the standard module * registry protocol. It returns release versions and, when present and valid, * the upstream source URL. * * https://developer.hashicorp.com/terraform/internals/module-registry-protocol */ async queryModuleRegistry(registryUrl, repository) { const pkgUrl = createSDBackendURL(registryUrl, "modules.v1", await this.getTerraformServiceDiscoveryResult(registryUrl), `${repository}/versions`); const { body: res } = await this.http.getJson(pkgUrl, ProtocolModuleResponse); return { releases: res.versions, sourceUrl: isHttpUrl(res.source) ? res.source : void 0 }; } static getCacheKey({ packageName, registryUrl }) { const { registry, repository } = getRegistryRepository(packageName, registryUrl); return `${registry}/${repository}`; } }; //#endregion export { TerraformModuleDatasource }; //# sourceMappingURL=index.js.map