From f42d0583d56f9094a79172149d5c3e9520af5a2c Mon Sep 17 00:00:00 2001 From: Sebastian Poxhofer <secustor@users.noreply.github.com> Date: Fri, 1 Dec 2023 12:58:43 +0100 Subject: [PATCH] refactor(utils/yaml): centralize YAML parsing to allow central templating handling (#26068) --- lib/modules/datasource/conan/index.ts | 2 +- lib/modules/datasource/custom/formats/yaml.ts | 6 +- lib/modules/datasource/helm/common.spec.ts | 2 +- lib/modules/datasource/helm/index.ts | 2 +- lib/modules/manager/argocd/extract.ts | 2 +- .../manager/azure-pipelines/extract.ts | 2 +- lib/modules/manager/batect/extract.ts | 2 +- lib/modules/manager/cloudbuild/extract.ts | 2 +- lib/modules/manager/crossplane/extract.ts | 2 +- lib/modules/manager/docker-compose/extract.ts | 2 +- lib/modules/manager/fleet/extract.ts | 2 +- lib/modules/manager/flux/extract.ts | 2 +- lib/modules/manager/github-actions/extract.ts | 2 +- .../manager/gitlabci-include/common.spec.ts | 2 +- .../manager/gitlabci-include/extract.ts | 2 +- lib/modules/manager/gitlabci/extract.ts | 2 +- .../manager/helm-requirements/extract.ts | 2 +- lib/modules/manager/helm-values/extract.ts | 2 +- lib/modules/manager/helmfile/extract.ts | 14 +-- lib/modules/manager/helmsman/extract.ts | 2 +- lib/modules/manager/helmv3/artifacts.ts | 2 +- lib/modules/manager/helmv3/extract.ts | 2 +- lib/modules/manager/helmv3/update.spec.ts | 2 +- lib/modules/manager/jenkins/extract.ts | 2 +- lib/modules/manager/kubernetes/extract.ts | 2 +- lib/modules/manager/kustomize/extract.ts | 2 +- lib/modules/manager/npm/extract/pnpm.spec.ts | 2 +- lib/modules/manager/npm/extract/pnpm.ts | 2 +- lib/modules/manager/npm/post-update/index.ts | 2 +- lib/modules/manager/npm/post-update/pnpm.ts | 2 +- lib/modules/manager/pre-commit/extract.ts | 2 +- lib/modules/manager/tekton/extract.ts | 2 +- lib/modules/manager/travis/extract.ts | 2 +- lib/modules/manager/velaci/extract.ts | 2 +- lib/modules/manager/woodpecker/extract.ts | 2 +- lib/util/schema-utils.ts | 2 +- lib/util/yaml.spec.ts | 115 ++++++++++++++++++ lib/util/yaml.ts | 41 +++++++ lib/workers/global/config/parse/file.ts | 2 +- 39 files changed, 199 insertions(+), 47 deletions(-) create mode 100644 lib/util/yaml.spec.ts create mode 100644 lib/util/yaml.ts diff --git a/lib/modules/datasource/conan/index.ts b/lib/modules/datasource/conan/index.ts index b8cc3d77d3..b4fae4da51 100644 --- a/lib/modules/datasource/conan/index.ts +++ b/lib/modules/datasource/conan/index.ts @@ -1,9 +1,9 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { cache } from '../../../util/cache/package/decorator'; import { GithubHttp } from '../../../util/http/github'; import { ensureTrailingSlash, joinUrlParts } from '../../../util/url'; +import { load } from '../../../util/yaml'; import * as allVersioning from '../../versioning'; import { Datasource } from '../datasource'; import type { diff --git a/lib/modules/datasource/custom/formats/yaml.ts b/lib/modules/datasource/custom/formats/yaml.ts index 076ded0a7f..f20f32d130 100644 --- a/lib/modules/datasource/custom/formats/yaml.ts +++ b/lib/modules/datasource/custom/formats/yaml.ts @@ -1,18 +1,18 @@ -import yaml from 'js-yaml'; import { readLocalFile } from '../../../../util/fs'; import type { Http } from '../../../../util/http'; +import { load } from '../../../../util/yaml'; import type { CustomDatasourceFetcher } from './types'; export class YamlFetcher implements CustomDatasourceFetcher { async fetch(http: Http, registryURL: string): Promise<unknown> { const response = await http.get(registryURL); - return yaml.load(response.body); + return load(response.body); } async readFile(registryURL: string): Promise<unknown> { const fileContent = await readLocalFile(registryURL, 'utf8'); - return yaml.load(fileContent!); + return load(fileContent!); } } diff --git a/lib/modules/datasource/helm/common.spec.ts b/lib/modules/datasource/helm/common.spec.ts index 2de9e3d13b..63db19e8c4 100644 --- a/lib/modules/datasource/helm/common.spec.ts +++ b/lib/modules/datasource/helm/common.spec.ts @@ -1,5 +1,5 @@ -import { load } from 'js-yaml'; import { Fixtures } from '../../../../test/fixtures'; +import { load } from '../../../util/yaml'; import { findSourceUrl } from './common'; import type { HelmRepository } from './types'; diff --git a/lib/modules/datasource/helm/index.ts b/lib/modules/datasource/helm/index.ts index 5f5eb92fde..aeff449f25 100644 --- a/lib/modules/datasource/helm/index.ts +++ b/lib/modules/datasource/helm/index.ts @@ -1,9 +1,9 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { cache } from '../../../util/cache/package/decorator'; import type { HttpResponse } from '../../../util/http/types'; import { ensureTrailingSlash } from '../../../util/url'; +import { load } from '../../../util/yaml'; import * as helmVersioning from '../../versioning/helm'; import { Datasource } from '../datasource'; import type { GetReleasesConfig, ReleaseResult } from '../types'; diff --git a/lib/modules/manager/argocd/extract.ts b/lib/modules/manager/argocd/extract.ts index 249fb4a9a9..8553a748f0 100644 --- a/lib/modules/manager/argocd/extract.ts +++ b/lib/modules/manager/argocd/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; import { trimTrailingSlash } from '../../../util/url'; +import { loadAll } from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { HelmDatasource } from '../../datasource/helm'; diff --git a/lib/modules/manager/azure-pipelines/extract.ts b/lib/modules/manager/azure-pipelines/extract.ts index 33f770c2f9..b5d353dec5 100644 --- a/lib/modules/manager/azure-pipelines/extract.ts +++ b/lib/modules/manager/azure-pipelines/extract.ts @@ -1,9 +1,9 @@ -import { load } from 'js-yaml'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; import { regEx } from '../../../util/regex'; import { joinUrlParts } from '../../../util/url'; +import { load } from '../../../util/yaml'; import { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { getDep } from '../dockerfile/extract'; diff --git a/lib/modules/manager/batect/extract.ts b/lib/modules/manager/batect/extract.ts index b2c8105dc2..fd9f4c4a03 100644 --- a/lib/modules/manager/batect/extract.ts +++ b/lib/modules/manager/batect/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import upath from 'upath'; import { logger } from '../../../logger'; import { readLocalFile } from '../../../util/fs'; +import { load } from '../../../util/yaml'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { id as dockerVersioning } from '../../versioning/docker'; import { id as semverVersioning } from '../../versioning/semver'; diff --git a/lib/modules/manager/cloudbuild/extract.ts b/lib/modules/manager/cloudbuild/extract.ts index b00c00e812..6f04657b95 100644 --- a/lib/modules/manager/cloudbuild/extract.ts +++ b/lib/modules/manager/cloudbuild/extract.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; +import { load } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency, PackageFileContent } from '../types'; diff --git a/lib/modules/manager/crossplane/extract.ts b/lib/modules/manager/crossplane/extract.ts index 35f70e8783..605a70fdf5 100644 --- a/lib/modules/manager/crossplane/extract.ts +++ b/lib/modules/manager/crossplane/extract.ts @@ -1,5 +1,5 @@ -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; +import { loadAll } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { ExtractConfig, diff --git a/lib/modules/manager/docker-compose/extract.ts b/lib/modules/manager/docker-compose/extract.ts index 67ffe6db23..06ccb81474 100644 --- a/lib/modules/manager/docker-compose/extract.ts +++ b/lib/modules/manager/docker-compose/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { ExtractConfig, PackageFileContent } from '../types'; import type { DockerComposeConfig } from './types'; diff --git a/lib/modules/manager/fleet/extract.ts b/lib/modules/manager/fleet/extract.ts index 65fa42d8de..cee52e074f 100644 --- a/lib/modules/manager/fleet/extract.ts +++ b/lib/modules/manager/fleet/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { regEx } from '../../../util/regex'; +import { loadAll } from '../../../util/yaml'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { HelmDatasource } from '../../datasource/helm'; import { checkIfStringIsPath } from '../terraform/util'; diff --git a/lib/modules/manager/flux/extract.ts b/lib/modules/manager/flux/extract.ts index 89c260319a..036c1a46f1 100644 --- a/lib/modules/manager/flux/extract.ts +++ b/lib/modules/manager/flux/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { readLocalFile } from '../../../util/fs'; import { regEx } from '../../../util/regex'; +import { loadAll } from '../../../util/yaml'; import { BitbucketTagsDatasource } from '../../datasource/bitbucket-tags'; import { DockerDatasource } from '../../datasource/docker'; import { GitRefsDatasource } from '../../datasource/git-refs'; diff --git a/lib/modules/manager/github-actions/extract.ts b/lib/modules/manager/github-actions/extract.ts index 4f0e59b5ae..e0415683c9 100644 --- a/lib/modules/manager/github-actions/extract.ts +++ b/lib/modules/manager/github-actions/extract.ts @@ -1,9 +1,9 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { isNotNullOrUndefined } from '../../../util/array'; import { newlineRegex, regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { GithubRunnersDatasource } from '../../datasource/github-runners'; import { GithubTagsDatasource } from '../../datasource/github-tags'; import * as dockerVersioning from '../../versioning/docker'; diff --git a/lib/modules/manager/gitlabci-include/common.spec.ts b/lib/modules/manager/gitlabci-include/common.spec.ts index 7484698925..c71f0cf03f 100644 --- a/lib/modules/manager/gitlabci-include/common.spec.ts +++ b/lib/modules/manager/gitlabci-include/common.spec.ts @@ -1,5 +1,5 @@ -import { load } from 'js-yaml'; import { Fixtures } from '../../../../test/fixtures'; +import { load } from '../../../util/yaml'; import type { GitlabPipeline } from '../gitlabci/types'; import { replaceReferenceTags } from '../gitlabci/utils'; import { diff --git a/lib/modules/manager/gitlabci-include/extract.ts b/lib/modules/manager/gitlabci-include/extract.ts index 9c4a289204..b38d730e48 100644 --- a/lib/modules/manager/gitlabci-include/extract.ts +++ b/lib/modules/manager/gitlabci-include/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; import type { GitlabInclude, diff --git a/lib/modules/manager/gitlabci/extract.ts b/lib/modules/manager/gitlabci/extract.ts index 00da59a140..a520e0349a 100644 --- a/lib/modules/manager/gitlabci/extract.ts +++ b/lib/modules/manager/gitlabci/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { readLocalFile } from '../../../util/fs'; import { trimLeadingSlash } from '../../../util/url'; +import { load } from '../../../util/yaml'; import type { ExtractConfig, PackageDependency, diff --git a/lib/modules/manager/helm-requirements/extract.ts b/lib/modules/manager/helm-requirements/extract.ts index 5a6a8567aa..52834af825 100644 --- a/lib/modules/manager/helm-requirements/extract.ts +++ b/lib/modules/manager/helm-requirements/extract.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; +import { load } from '../../../util/yaml'; import { HelmDatasource } from '../../datasource/helm'; import type { ExtractConfig, diff --git a/lib/modules/manager/helm-values/extract.ts b/lib/modules/manager/helm-values/extract.ts index 1f9ea32f61..e75026dec8 100644 --- a/lib/modules/manager/helm-values/extract.ts +++ b/lib/modules/manager/helm-values/extract.ts @@ -1,5 +1,5 @@ -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; +import { loadAll } from '../../../util/yaml'; import { id as dockerVersioning } from '../../versioning/docker'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency, PackageFileContent } from '../types'; diff --git a/lib/modules/manager/helmfile/extract.ts b/lib/modules/manager/helmfile/extract.ts index 0a29612900..0ca299a223 100644 --- a/lib/modules/manager/helmfile/extract.ts +++ b/lib/modules/manager/helmfile/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { regEx } from '../../../util/regex'; +import { loadAll } from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { HelmDatasource } from '../../datasource/helm'; import type { @@ -18,13 +18,6 @@ import { const isValidChartName = (name: string | undefined): boolean => !!name && !regEx(/[!@#$%^&*(),.?":{}/|<>A-Z]/).test(name); -function extractYaml(content: string): string { - // regex remove go templated ({{ . }}) values - return content - .replace(regEx(/{{`.+?`}}/gs), '') - .replace(regEx(/{{.+?}}/g), ''); -} - function isLocalPath(possiblePath: string): boolean { return ['./', '../', '/'].some((localPrefix) => possiblePath.startsWith(localPrefix), @@ -42,7 +35,10 @@ export async function extractPackageFile( // Record kustomization usage for all deps, since updating artifacts is run on the helmfile.yaml as a whole. let needKustomize = false; try { - docs = loadAll(extractYaml(content), null, { json: true }) as Doc[]; + docs = loadAll(content, null, { + removeTemplates: true, + json: true, + }) as Doc[]; } catch (err) { logger.debug( { err, packageFile }, diff --git a/lib/modules/manager/helmsman/extract.ts b/lib/modules/manager/helmsman/extract.ts index 504b2f43af..f776cd0b2f 100644 --- a/lib/modules/manager/helmsman/extract.ts +++ b/lib/modules/manager/helmsman/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { HelmDatasource } from '../../datasource/helm'; import type { diff --git a/lib/modules/manager/helmv3/artifacts.ts b/lib/modules/manager/helmv3/artifacts.ts index 93616df86e..7f7df8d6c6 100644 --- a/lib/modules/manager/helmv3/artifacts.ts +++ b/lib/modules/manager/helmv3/artifacts.ts @@ -1,5 +1,4 @@ import is from '@sindresorhus/is'; -import yaml from 'js-yaml'; import pMap from 'p-map'; import { quote } from 'shlex'; import { TEMPORARY_ERROR } from '../../../constants/error-messages'; @@ -14,6 +13,7 @@ import { } from '../../../util/fs'; import { getRepoStatus } from '../../../util/git'; import * as hostRules from '../../../util/host-rules'; +import * as yaml from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { HelmDatasource } from '../../datasource/helm'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; diff --git a/lib/modules/manager/helmv3/extract.ts b/lib/modules/manager/helmv3/extract.ts index d7fc59518c..f6d9e9d464 100644 --- a/lib/modules/manager/helmv3/extract.ts +++ b/lib/modules/manager/helmv3/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { getSiblingFileName, localPathExists } from '../../../util/fs'; +import { load } from '../../../util/yaml'; import { HelmDatasource } from '../../datasource/helm'; import type { ExtractConfig, diff --git a/lib/modules/manager/helmv3/update.spec.ts b/lib/modules/manager/helmv3/update.spec.ts index 43062508b6..854dcfc2e8 100644 --- a/lib/modules/manager/helmv3/update.spec.ts +++ b/lib/modules/manager/helmv3/update.spec.ts @@ -1,4 +1,4 @@ -import { dump } from 'js-yaml'; +import { dump } from '../../../util/yaml'; import * as helmv3Updater from '.'; describe('modules/manager/helmv3/update', () => { diff --git a/lib/modules/manager/jenkins/extract.ts b/lib/modules/manager/jenkins/extract.ts index c8b1dad120..51d3fa54ac 100644 --- a/lib/modules/manager/jenkins/extract.ts +++ b/lib/modules/manager/jenkins/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { isSkipComment } from '../../../util/ignore'; import { newlineRegex, regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { JenkinsPluginsDatasource } from '../../datasource/jenkins-plugins'; import * as mavenVersioning from '../../versioning/maven'; import type { PackageDependency, PackageFileContent } from '../types'; diff --git a/lib/modules/manager/kubernetes/extract.ts b/lib/modules/manager/kubernetes/extract.ts index 4588f63d1f..9920f16007 100644 --- a/lib/modules/manager/kubernetes/extract.ts +++ b/lib/modules/manager/kubernetes/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; +import { loadAll } from '../../../util/yaml'; import { KubernetesApiDatasource, supportedApis, diff --git a/lib/modules/manager/kustomize/extract.ts b/lib/modules/manager/kustomize/extract.ts index 8af061713a..bca4d553c0 100644 --- a/lib/modules/manager/kustomize/extract.ts +++ b/lib/modules/manager/kustomize/extract.ts @@ -1,8 +1,8 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; import { regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { GithubTagsDatasource } from '../../datasource/github-tags'; diff --git a/lib/modules/manager/npm/extract/pnpm.spec.ts b/lib/modules/manager/npm/extract/pnpm.spec.ts index 9927655a77..590a941f9f 100644 --- a/lib/modules/manager/npm/extract/pnpm.spec.ts +++ b/lib/modules/manager/npm/extract/pnpm.spec.ts @@ -1,8 +1,8 @@ -import yaml from 'js-yaml'; import { Fixtures } from '../../../../../test/fixtures'; import { getFixturePath, logger, partial } from '../../../../../test/util'; import { GlobalConfig } from '../../../../config/global'; import * as fs from '../../../../util/fs'; +import * as yaml from '../../../../util/yaml'; import type { PackageFile } from '../../types'; import type { NpmManagerData } from '../types'; import { diff --git a/lib/modules/manager/npm/extract/pnpm.ts b/lib/modules/manager/npm/extract/pnpm.ts index 3de992b460..d358212cdb 100644 --- a/lib/modules/manager/npm/extract/pnpm.ts +++ b/lib/modules/manager/npm/extract/pnpm.ts @@ -1,6 +1,5 @@ import is from '@sindresorhus/is'; import { findPackages } from 'find-packages'; -import { load } from 'js-yaml'; import upath from 'upath'; import { GlobalConfig } from '../../../../config/global'; import { logger } from '../../../../logger'; @@ -10,6 +9,7 @@ import { localPathExists, readLocalFile, } from '../../../../util/fs'; +import { load } from '../../../../util/yaml'; import type { PackageFile } from '../../types'; import type { PnpmDependencySchema, PnpmLockFile } from '../post-update/types'; import type { NpmManagerData } from '../types'; diff --git a/lib/modules/manager/npm/post-update/index.ts b/lib/modules/manager/npm/post-update/index.ts index 5b8d92b4e1..fa318343b0 100644 --- a/lib/modules/manager/npm/post-update/index.ts +++ b/lib/modules/manager/npm/post-update/index.ts @@ -1,7 +1,6 @@ // TODO: types (#22198) import is from '@sindresorhus/is'; import deepmerge from 'deepmerge'; -import { dump, load } from 'js-yaml'; import upath from 'upath'; import { logger } from '../../../../logger'; import { ExternalHostError } from '../../../../types/errors/external-host-error'; @@ -18,6 +17,7 @@ import type { FileChange } from '../../../../util/git/types'; import * as hostRules from '../../../../util/host-rules'; import { newlineRegex, regEx } from '../../../../util/regex'; import { ensureTrailingSlash } from '../../../../util/url'; +import { dump, load } from '../../../../util/yaml'; import { NpmDatasource } from '../../../datasource/npm'; import { scm } from '../../../platform/scm'; import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types'; diff --git a/lib/modules/manager/npm/post-update/pnpm.ts b/lib/modules/manager/npm/post-update/pnpm.ts index c3db89f25a..9cbffebfde 100644 --- a/lib/modules/manager/npm/post-update/pnpm.ts +++ b/lib/modules/manager/npm/post-update/pnpm.ts @@ -1,5 +1,4 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import upath from 'upath'; import { GlobalConfig } from '../../../../config/global'; import { TEMPORARY_ERROR } from '../../../../constants/error-messages'; @@ -11,6 +10,7 @@ import type { ToolConstraint, } from '../../../../util/exec/types'; import { deleteLocalFile, readLocalFile } from '../../../../util/fs'; +import { load } from '../../../../util/yaml'; import type { PostUpdateConfig, Upgrade } from '../../types'; import { getNodeToolConstraint } from './node-version'; import type { GenerateLockFileResult, PnpmLockFile } from './types'; diff --git a/lib/modules/manager/pre-commit/extract.ts b/lib/modules/manager/pre-commit/extract.ts index 30a6eac49c..345e3d66d9 100644 --- a/lib/modules/manager/pre-commit/extract.ts +++ b/lib/modules/manager/pre-commit/extract.ts @@ -1,10 +1,10 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import type { SkipReason } from '../../../types'; import { detectPlatform } from '../../../util/common'; import { find } from '../../../util/host-rules'; import { regEx } from '../../../util/regex'; +import { load } from '../../../util/yaml'; import { GithubTagsDatasource } from '../../datasource/github-tags'; import { GitlabTagsDatasource } from '../../datasource/gitlab-tags'; import type { PackageDependency, PackageFileContent } from '../types'; diff --git a/lib/modules/manager/tekton/extract.ts b/lib/modules/manager/tekton/extract.ts index 810a4a8673..9c4ab35d74 100644 --- a/lib/modules/manager/tekton/extract.ts +++ b/lib/modules/manager/tekton/extract.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; -import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; +import { loadAll } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency, PackageFileContent } from '../types'; import type { diff --git a/lib/modules/manager/travis/extract.ts b/lib/modules/manager/travis/extract.ts index 886cc4a0f4..9427813c07 100644 --- a/lib/modules/manager/travis/extract.ts +++ b/lib/modules/manager/travis/extract.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; +import { load } from '../../../util/yaml'; import { GithubTagsDatasource } from '../../datasource/github-tags'; import type { PackageDependency, PackageFileContent } from '../types'; import type { TravisMatrixItem, TravisYaml } from './types'; diff --git a/lib/modules/manager/velaci/extract.ts b/lib/modules/manager/velaci/extract.ts index 50ea39a6ea..6be65899f0 100644 --- a/lib/modules/manager/velaci/extract.ts +++ b/lib/modules/manager/velaci/extract.ts @@ -1,6 +1,6 @@ -import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; +import { load } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency, PackageFileContent } from '../types'; import type { VelaPipelineConfiguration } from './types'; diff --git a/lib/modules/manager/woodpecker/extract.ts b/lib/modules/manager/woodpecker/extract.ts index 6012709aaf..a5fabef1c7 100644 --- a/lib/modules/manager/woodpecker/extract.ts +++ b/lib/modules/manager/woodpecker/extract.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; -import { load } from 'js-yaml'; import { logger } from '../../../logger'; +import { load } from '../../../util/yaml'; import { getDep } from '../dockerfile/extract'; import type { ExtractConfig, PackageFileContent } from '../types'; import type { WoodpeckerConfig } from './types'; diff --git a/lib/util/schema-utils.ts b/lib/util/schema-utils.ts index f2b5bed1e4..28698d2c8f 100644 --- a/lib/util/schema-utils.ts +++ b/lib/util/schema-utils.ts @@ -1,9 +1,9 @@ -import { load, loadAll } from 'js-yaml'; import JSON5 from 'json5'; import { DateTime } from 'luxon'; import type { JsonArray, JsonValue } from 'type-fest'; import { z } from 'zod'; import { parse as parseToml } from './toml'; +import { load, loadAll } from './yaml'; interface ErrorContext<T> { error: z.ZodError; diff --git a/lib/util/yaml.spec.ts b/lib/util/yaml.spec.ts new file mode 100644 index 0000000000..39b1ba55a0 --- /dev/null +++ b/lib/util/yaml.spec.ts @@ -0,0 +1,115 @@ +import { codeBlock } from 'common-tags'; +import { load, loadAll } from './yaml'; + +describe('util/yaml', () => { + describe('loadAll', () => { + it('should return empty array for empty string', () => { + expect(loadAll(``)).toEqual([]); + }); + + it('should parse content with single document', () => { + expect( + loadAll(codeBlock` + myObject: + aString: value + `), + ).toEqual([ + { + myObject: { + aString: 'value', + }, + }, + ]); + }); + + it('should parse content with multiple documents', () => { + expect( + loadAll(codeBlock` + myObject: + aString: value + --- + foo: bar + `), + ).toEqual([ + { + myObject: { + aString: 'value', + }, + }, + { + foo: 'bar', + }, + ]); + }); + + it('should parse content with templates', () => { + expect( + loadAll( + codeBlock` + myObject: + aString: {{ value }} + --- + foo: {{ foo.bar }} + `, + undefined, + { removeTemplates: true }, + ), + ).toEqual([ + { + myObject: { + aString: null, + }, + }, + { + foo: null, + }, + ]); + }); + }); + + describe('load', () => { + it('should return undefined', () => { + expect(load(``)).toBeUndefined(); + }); + + it('should parse content with single document', () => { + expect( + load(codeBlock` + myObject: + aString: value + `), + ).toEqual({ + myObject: { + aString: 'value', + }, + }); + }); + + it('should parse content with multiple documents', () => { + expect(() => + load(codeBlock` + myObject: + aString: value + --- + foo: bar + `), + ).toThrow(); + }); + + it('should parse content with template', () => { + expect( + load( + codeBlock` + myObject: + aString: {{value}} + `, + { removeTemplates: true }, + ), + ).toEqual({ + myObject: { + aString: null, + }, + }); + }); + }); +}); diff --git a/lib/util/yaml.ts b/lib/util/yaml.ts new file mode 100644 index 0000000000..620c330dfa --- /dev/null +++ b/lib/util/yaml.ts @@ -0,0 +1,41 @@ +import { + DumpOptions, + LoadOptions, + loadAll as multiple, + load as single, + dump as upstreamDump, +} from 'js-yaml'; +import { regEx } from './regex'; + +interface YamlOptions extends LoadOptions { + removeTemplates?: boolean; +} + +export function loadAll( + content: string, + iterator?: null | undefined, + options?: YamlOptions, +): unknown[] { + const massagedContent = massageContent(content, options); + + return multiple(massagedContent, iterator, options); +} + +export function load(content: string, options?: YamlOptions): unknown { + const massagedContent = massageContent(content, options); + return single(massagedContent, options); +} + +export function dump(obj: any, opts?: DumpOptions | undefined): string { + return upstreamDump(obj, opts); +} + +function massageContent(content: string, options?: YamlOptions): string { + if (options?.removeTemplates) { + return content + .replace(regEx(/{{`.+?`}}/gs), '') + .replace(regEx(/{{.+?}}/g), ''); + } + + return content; +} diff --git a/lib/workers/global/config/parse/file.ts b/lib/workers/global/config/parse/file.ts index 3d0ecb7d9d..f66cee56d1 100644 --- a/lib/workers/global/config/parse/file.ts +++ b/lib/workers/global/config/parse/file.ts @@ -1,6 +1,5 @@ import is from '@sindresorhus/is'; import fs from 'fs-extra'; -import { load } from 'js-yaml'; import JSON5 from 'json5'; import upath from 'upath'; import { migrateConfig } from '../../../../config/migration'; @@ -8,6 +7,7 @@ import type { AllConfig, RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import { parseJson } from '../../../../util/common'; import { readSystemFile } from '../../../../util/fs'; +import { load } from '../../../../util/yaml'; export async function getParsedContent(file: string): Promise<RenovateConfig> { if (upath.basename(file) === '.renovaterc') { -- GitLab