diff --git a/lib/modules/manager/terraform/__fixtures__/tfeWorkspace.tf b/lib/modules/manager/terraform/__fixtures__/tfeWorkspace.tf index 17477f65cba7d693481e3262070ee358bd98176f..164e7bd51deca0794d6a7555782726ce75bb4fb3 100644 --- a/lib/modules/manager/terraform/__fixtures__/tfeWorkspace.tf +++ b/lib/modules/manager/terraform/__fixtures__/tfeWorkspace.tf @@ -9,3 +9,15 @@ resource "tfe_workspace" "test_workspace" { name = "test-workspace" organization = "renovate-fixtures" } + +resource "tfe_workspace" "workspace_with_block" { + vcs_repo { + identifier = "organization/repository" + oauth_token_id = "invalidToken" + } + + name = "lifecycle-workspace" + organization = "renovate-fixtures" + + terraform_version = "1.1.9" +} diff --git a/lib/modules/manager/terraform/__snapshots__/extract.spec.ts.snap b/lib/modules/manager/terraform/__snapshots__/extract.spec.ts.snap index bc2084b3ff85bd3eaa5a369612a420a2fe2e4bfc..1ee1db241e232a0a1885b219b0590241998704a3 100644 --- a/lib/modules/manager/terraform/__snapshots__/extract.spec.ts.snap +++ b/lib/modules/manager/terraform/__snapshots__/extract.spec.ts.snap @@ -460,6 +460,13 @@ Object { Object { "skipReason": "no-version", }, + Object { + "currentValue": "1.1.9", + "datasource": "github-tags", + "depName": "hashicorp/terraform", + "depType": "tfe_workspace", + "extractVersion": "v(?<version>.*)$", + }, ], } `; diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts index 9d3acaafa05e0591b6c7aab6d9b34360d151d12d..ff8c7001d5497af3230a63e47fc4ebd807ffa6cb 100644 --- a/lib/modules/manager/terraform/extract.spec.ts +++ b/lib/modules/manager/terraform/extract.spec.ts @@ -109,7 +109,7 @@ describe('modules/manager/terraform/extract', () => { {} ); expect(res).toMatchSnapshot(); - expect(res.deps).toHaveLength(2); + expect(res.deps).toHaveLength(3); expect(res.deps.filter((dep) => dep.skipReason)).toHaveLength(1); }); }); diff --git a/lib/modules/manager/terraform/providers.ts b/lib/modules/manager/terraform/providers.ts index e8b026a1c1be9e675d946b69fae619a6f7dafa00..07ec08caaf5d2b52ae7e5fc5f71af4bed79c3b65 100644 --- a/lib/modules/manager/terraform/providers.ts +++ b/lib/modules/manager/terraform/providers.ts @@ -40,7 +40,7 @@ export function extractTerraformProvider( // istanbul ignore else if (is.string(line)) { - // `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block + // `{` will be counted with +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block const openBrackets = (line.match(regEx(/\{/g)) || []).length; const closedBrackets = (line.match(regEx(/\}/g)) || []).length; braceCounter = braceCounter + openBrackets - closedBrackets; diff --git a/lib/modules/manager/terraform/resources.ts b/lib/modules/manager/terraform/resources.ts index 3d717aa098a1f5e20f65d3b0bd9d763f5f4de24d..587b52aac0b8ca8d5b23a24d2bae21760c3954ef 100644 --- a/lib/modules/manager/terraform/resources.ts +++ b/lib/modules/manager/terraform/resources.ts @@ -1,3 +1,6 @@ +import is from '@sindresorhus/is'; +import { logger } from '../../../logger'; +import { regEx } from '../../../util/regex'; import { HelmDatasource } from '../../datasource/helm'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency } from '../types'; @@ -23,7 +26,7 @@ export function extractTerraformResource( lines: string[] ): ExtractionResult { let lineNumber = startingLine; - let line = lines[lineNumber]; + const line = lines[lineNumber]; const deps: PackageDependency<ResourceManagerData>[] = []; const managerData: ResourceManagerData = { terraformDependencyType: TerraformDependencyTypes.resource, @@ -43,29 +46,50 @@ export function extractTerraformResource( * Iterates over all lines of the resource to extract the relevant key value pairs, * e.g. the chart name for helm charts or the terraform_version for tfe_workspace */ + let braceCounter = 0; do { - lineNumber += 1; - line = lines[lineNumber]; - const kvMatch = keyValueExtractionRegex.exec(line); - if (kvMatch?.groups) { - switch (kvMatch.groups.key) { - case 'chart': - case 'image': - case 'name': - case 'repository': - managerData[kvMatch.groups.key] = kvMatch.groups.value; - break; - case 'version': - case 'terraform_version': - dep.currentValue = kvMatch.groups.value; - break; - default: - /* istanbul ignore next */ - break; + // istanbul ignore if + if (lineNumber > lines.length - 1) { + logger.debug(`Malformed Terraform file detected.`); + } + + const line = lines[lineNumber]; + + // istanbul ignore else + if (is.string(line)) { + // `{` will be counted with +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block + const openBrackets = (line.match(regEx(/\{/g)) || []).length; + const closedBrackets = (line.match(regEx(/\}/g)) || []).length; + braceCounter = braceCounter + openBrackets - closedBrackets; + + const kvMatch = keyValueExtractionRegex.exec(line); + if (kvMatch?.groups) { + switch (kvMatch.groups.key) { + case 'chart': + case 'image': + case 'name': + case 'repository': + managerData[kvMatch.groups.key] = kvMatch.groups.value; + break; + case 'version': + case 'terraform_version': + dep.currentValue = kvMatch.groups.value; + break; + default: + /* istanbul ignore next */ + break; + } } + } else { + // stop - something went wrong + braceCounter = 0; } - } while (line.trim() !== '}'); + lineNumber += 1; + } while (braceCounter !== 0); deps.push(dep); + + // remove last lineNumber addition to not skip a line after the last bracket + lineNumber -= 1; return { lineNumber, dependencies: deps }; }