renovate 44.210.2 → 44.211.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/options/index.js +1 -1
- package/dist/config/options/index.js.map +1 -1
- package/dist/config/utils.js +2 -1
- package/dist/config/utils.js.map +1 -1
- package/dist/config/validation-helpers/regex-glob-matchers.js.map +1 -1
- package/dist/config/validation-helpers/utils.js +5 -1
- package/dist/config/validation-helpers/utils.js.map +1 -1
- package/dist/config/validation.js +8 -2
- package/dist/config/validation.js.map +1 -1
- package/dist/config-validator.js +1 -1
- package/dist/config-validator.js.map +1 -1
- package/dist/global-config-option-defaults.generated.js +1 -1
- package/dist/global-config-option-defaults.generated.js.map +1 -1
- package/dist/instrumentation/index.js +3 -2
- package/dist/instrumentation/index.js.map +1 -1
- package/dist/logger/bunyan.js +3 -2
- package/dist/logger/bunyan.js.map +1 -1
- package/dist/logger/pretty-stdout.js +2 -1
- package/dist/logger/pretty-stdout.js.map +1 -1
- package/dist/modules/datasource/apk/index.js +2 -2
- package/dist/modules/datasource/apk/index.js.map +1 -1
- package/dist/modules/datasource/artifactory/index.js +2 -3
- package/dist/modules/datasource/artifactory/index.js.map +1 -1
- package/dist/modules/datasource/bazel/index.js +2 -1
- package/dist/modules/datasource/bazel/index.js.map +1 -1
- package/dist/modules/datasource/cdnjs/index.js +2 -1
- package/dist/modules/datasource/cdnjs/index.js.map +1 -1
- package/dist/modules/datasource/conda/index.js +2 -1
- package/dist/modules/datasource/conda/index.js.map +1 -1
- package/dist/modules/datasource/crate/index.js +2 -1
- package/dist/modules/datasource/crate/index.js.map +1 -1
- package/dist/modules/datasource/dart-version/index.js +2 -1
- package/dist/modules/datasource/dart-version/index.js.map +1 -1
- package/dist/modules/datasource/datasource.js +2 -2
- package/dist/modules/datasource/datasource.js.map +1 -1
- package/dist/modules/datasource/deb/url.js +3 -1
- package/dist/modules/datasource/deb/url.js.map +1 -1
- package/dist/modules/datasource/devbox/index.js +2 -1
- package/dist/modules/datasource/devbox/index.js.map +1 -1
- package/dist/modules/datasource/docker/common.js +10 -8
- package/dist/modules/datasource/docker/common.js.map +1 -1
- package/dist/modules/datasource/docker/ecr.js +2 -1
- package/dist/modules/datasource/docker/ecr.js.map +1 -1
- package/dist/modules/datasource/docker/index.js +20 -17
- package/dist/modules/datasource/docker/index.js.map +1 -1
- package/dist/modules/datasource/gitea-tags/base.js +2 -3
- package/dist/modules/datasource/gitea-tags/base.js.map +1 -1
- package/dist/modules/datasource/github-tags/index.js +2 -1
- package/dist/modules/datasource/github-tags/index.js.map +1 -1
- package/dist/modules/datasource/gitlab-tags/index.js +2 -3
- package/dist/modules/datasource/gitlab-tags/index.js.map +1 -1
- package/dist/modules/datasource/go/base.js +1 -1
- package/dist/modules/datasource/go/base.js.map +1 -1
- package/dist/modules/datasource/go/common.js +8 -2
- package/dist/modules/datasource/go/common.js.map +1 -1
- package/dist/modules/datasource/go/env.js +2 -1
- package/dist/modules/datasource/go/env.js.map +1 -1
- package/dist/modules/datasource/go/releases-goproxy.js +7 -5
- package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
- package/dist/modules/datasource/helm/index.js +2 -1
- package/dist/modules/datasource/helm/index.js.map +1 -1
- package/dist/modules/datasource/hexpm-bob/index.js +2 -1
- package/dist/modules/datasource/hexpm-bob/index.js.map +1 -1
- package/dist/modules/datasource/index.js +4 -3
- package/dist/modules/datasource/index.js.map +1 -1
- package/dist/modules/datasource/java-version/adoptium.js +3 -2
- package/dist/modules/datasource/java-version/adoptium.js.map +1 -1
- package/dist/modules/datasource/java-version/graalvm.js +2 -1
- package/dist/modules/datasource/java-version/graalvm.js.map +1 -1
- package/dist/modules/datasource/maven/index.js.map +1 -1
- package/dist/modules/datasource/maven/util.js +7 -10
- package/dist/modules/datasource/maven/util.js.map +1 -1
- package/dist/modules/datasource/npm/npmrc.js +2 -2
- package/dist/modules/datasource/npm/npmrc.js.map +1 -1
- package/dist/modules/datasource/nuget/v3.js +3 -5
- package/dist/modules/datasource/nuget/v3.js.map +1 -1
- package/dist/modules/datasource/packagist/index.js +4 -5
- package/dist/modules/datasource/packagist/index.js.map +1 -1
- package/dist/modules/datasource/pod/index.js +4 -4
- package/dist/modules/datasource/pod/index.js.map +1 -1
- package/dist/modules/datasource/pypi/index.js +19 -11
- package/dist/modules/datasource/pypi/index.js.map +1 -1
- package/dist/modules/datasource/python-version/index.js +2 -3
- package/dist/modules/datasource/python-version/index.js.map +1 -1
- package/dist/modules/datasource/repology/index.js +4 -3
- package/dist/modules/datasource/repology/index.js.map +1 -1
- package/dist/modules/datasource/rpm/providers/common.js +3 -1
- package/dist/modules/datasource/rpm/providers/common.js.map +1 -1
- package/dist/modules/datasource/rubygems/index.js +2 -5
- package/dist/modules/datasource/rubygems/index.js.map +1 -1
- package/dist/modules/datasource/rubygems/versions-endpoint-cache.js +13 -18
- package/dist/modules/datasource/rubygems/versions-endpoint-cache.js.map +1 -1
- package/dist/modules/datasource/terraform-module/base.js +2 -1
- package/dist/modules/datasource/terraform-module/base.js.map +1 -1
- package/dist/modules/datasource/terraform-provider/index.js +2 -3
- package/dist/modules/datasource/terraform-provider/index.js.map +1 -1
- package/dist/modules/manager/bazel-module/parser/context.js +0 -1
- package/dist/modules/manager/bazel-module/parser/context.js.map +1 -1
- package/dist/modules/manager/bundler/host-rules.js +4 -1
- package/dist/modules/manager/bundler/host-rules.js.map +1 -1
- package/dist/modules/manager/composer/range.js +1 -1
- package/dist/modules/manager/composer/range.js.map +1 -1
- package/dist/modules/manager/custom/utils.js +3 -1
- package/dist/modules/manager/custom/utils.js.map +1 -1
- package/dist/modules/manager/devbox/schema.js +2 -1
- package/dist/modules/manager/devbox/schema.js.map +1 -1
- package/dist/modules/manager/dockerfile/extract.js +10 -2
- package/dist/modules/manager/dockerfile/extract.js.map +1 -1
- package/dist/modules/manager/fingerprint.generated.js +1 -1
- package/dist/modules/manager/fingerprint.generated.js.map +1 -1
- package/dist/modules/manager/github-actions/parse.js +2 -1
- package/dist/modules/manager/github-actions/parse.js.map +1 -1
- package/dist/modules/manager/gomod/artifacts.js +5 -2
- package/dist/modules/manager/gomod/artifacts.js.map +1 -1
- package/dist/modules/manager/gradle/artifacts.js +5 -2
- package/dist/modules/manager/gradle/artifacts.js.map +1 -1
- package/dist/modules/manager/gradle/utils.js +2 -1
- package/dist/modules/manager/gradle/utils.js.map +1 -1
- package/dist/modules/manager/gradle-wrapper/utils.js +9 -5
- package/dist/modules/manager/gradle-wrapper/utils.js.map +1 -1
- package/dist/modules/manager/helm-values/util.js +1 -1
- package/dist/modules/manager/helm-values/util.js.map +1 -1
- package/dist/modules/manager/helmfile/artifacts.js +1 -1
- package/dist/modules/manager/helmfile/artifacts.js.map +1 -1
- package/dist/modules/manager/helmv3/artifacts.js +1 -1
- package/dist/modules/manager/helmv3/artifacts.js.map +1 -1
- package/dist/modules/manager/maven/extract.js +5 -2
- package/dist/modules/manager/maven/extract.js.map +1 -1
- package/dist/modules/manager/maven-wrapper/artifacts.js +3 -2
- package/dist/modules/manager/maven-wrapper/artifacts.js.map +1 -1
- package/dist/modules/manager/mise/artifacts.js +2 -1
- package/dist/modules/manager/mise/artifacts.js.map +1 -1
- package/dist/modules/manager/mise/extract.js.map +1 -1
- package/dist/modules/manager/npm/artifacts.js +3 -1
- package/dist/modules/manager/npm/artifacts.js.map +1 -1
- package/dist/modules/manager/npm/extract/common/dependency.js +4 -1
- package/dist/modules/manager/npm/extract/common/dependency.js.map +1 -1
- package/dist/modules/manager/npm/extract/common/package-file.js +2 -1
- package/dist/modules/manager/npm/extract/common/package-file.js.map +1 -1
- package/dist/modules/manager/npm/extract/index.js.map +1 -1
- package/dist/modules/manager/npm/extract/post/locked-versions.js.map +1 -1
- package/dist/modules/manager/npm/npmrc.js +2 -1
- package/dist/modules/manager/npm/npmrc.js.map +1 -1
- package/dist/modules/manager/npm/post-update/index.js +2 -1
- package/dist/modules/manager/npm/post-update/index.js.map +1 -1
- package/dist/modules/manager/npm/post-update/npm.js +2 -3
- package/dist/modules/manager/npm/post-update/npm.js.map +1 -1
- package/dist/modules/manager/npm/post-update/yarn.js.map +1 -1
- package/dist/modules/manager/npm/schema.js +6 -2
- package/dist/modules/manager/npm/schema.js.map +1 -1
- package/dist/modules/manager/npm/update/dependency/index.js +3 -2
- package/dist/modules/manager/npm/update/dependency/index.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js +6 -2
- package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/package-lock/get-locked.js +2 -1
- package/dist/modules/manager/npm/update/locked-dependency/package-lock/get-locked.js.map +1 -1
- package/dist/modules/manager/nuget/package-tree.js +2 -1
- package/dist/modules/manager/nuget/package-tree.js.map +1 -1
- package/dist/modules/manager/paket/update-locked.js +4 -1
- package/dist/modules/manager/paket/update-locked.js.map +1 -1
- package/dist/modules/manager/pipenv/extract.js +4 -1
- package/dist/modules/manager/pipenv/extract.js.map +1 -1
- package/dist/modules/platform/azure/azure-helper.js +2 -1
- package/dist/modules/platform/azure/azure-helper.js.map +1 -1
- package/dist/modules/platform/azure/index.js +7 -3
- package/dist/modules/platform/azure/index.js.map +1 -1
- package/dist/modules/platform/bitbucket/index.js +13 -6
- package/dist/modules/platform/bitbucket/index.js.map +1 -1
- package/dist/modules/platform/bitbucket-server/index.js +13 -9
- package/dist/modules/platform/bitbucket-server/index.js.map +1 -1
- package/dist/modules/platform/codecommit/index.js +2 -2
- package/dist/modules/platform/codecommit/index.js.map +1 -1
- package/dist/modules/platform/gerrit/client.js +4 -1
- package/dist/modules/platform/gerrit/client.js.map +1 -1
- package/dist/modules/platform/gerrit/index.js +3 -2
- package/dist/modules/platform/gerrit/index.js.map +1 -1
- package/dist/modules/platform/gitea/gitea-helper.js +5 -4
- package/dist/modules/platform/gitea/gitea-helper.js.map +1 -1
- package/dist/modules/platform/gitea/index.js +11 -4
- package/dist/modules/platform/gitea/index.js.map +1 -1
- package/dist/modules/platform/github/index.js +36 -23
- package/dist/modules/platform/github/index.js.map +1 -1
- package/dist/modules/platform/gitlab/index.js +16 -9
- package/dist/modules/platform/gitlab/index.js.map +1 -1
- package/dist/modules/platform/scm-manager/index.js +4 -1
- package/dist/modules/platform/scm-manager/index.js.map +1 -1
- package/dist/modules/platform/scm-manager/utils.js +2 -1
- package/dist/modules/platform/scm-manager/utils.js.map +1 -1
- package/dist/modules/versioning/cargo/index.js.map +1 -1
- package/dist/modules/versioning/composer/index.js +2 -1
- package/dist/modules/versioning/composer/index.js.map +1 -1
- package/dist/modules/versioning/conan/common.js +4 -1
- package/dist/modules/versioning/conan/common.js.map +1 -1
- package/dist/modules/versioning/debian/index.js +2 -1
- package/dist/modules/versioning/debian/index.js.map +1 -1
- package/dist/modules/versioning/gradle/compare.js +2 -1
- package/dist/modules/versioning/gradle/compare.js.map +1 -1
- package/dist/modules/versioning/hex/index.js +2 -1
- package/dist/modules/versioning/hex/index.js.map +1 -1
- package/dist/modules/versioning/julia/index.js.map +1 -1
- package/dist/modules/versioning/maven/compare.js +17 -7
- package/dist/modules/versioning/maven/compare.js.map +1 -1
- package/dist/modules/versioning/npm/index.js +2 -1
- package/dist/modules/versioning/npm/index.js.map +1 -1
- package/dist/modules/versioning/npm/range.js.map +1 -1
- package/dist/modules/versioning/paket/index.js +2 -1
- package/dist/modules/versioning/paket/index.js.map +1 -1
- package/dist/modules/versioning/paket/range.js +7 -3
- package/dist/modules/versioning/paket/range.js.map +1 -1
- package/dist/modules/versioning/pep440/index.js +2 -1
- package/dist/modules/versioning/pep440/index.js.map +1 -1
- package/dist/modules/versioning/poetry/index.js +2 -1
- package/dist/modules/versioning/poetry/index.js.map +1 -1
- package/dist/modules/versioning/regex/index.js +1 -1
- package/dist/modules/versioning/regex/index.js.map +1 -1
- package/dist/modules/versioning/rez/index.js +2 -1
- package/dist/modules/versioning/rez/index.js.map +1 -1
- package/dist/modules/versioning/vcpkg/index.js +2 -1
- package/dist/modules/versioning/vcpkg/index.js.map +1 -1
- package/dist/util/cache/package/impl/base.js +2 -1
- package/dist/util/cache/package/impl/base.js.map +1 -1
- package/dist/util/cache/package/with-cache.js +2 -1
- package/dist/util/cache/package/with-cache.js.map +1 -1
- package/dist/util/check-token.js +7 -4
- package/dist/util/check-token.js.map +1 -1
- package/dist/util/exec/utils.js +4 -1
- package/dist/util/exec/utils.js.map +1 -1
- package/dist/util/git/auth.js +5 -1
- package/dist/util/git/auth.js.map +1 -1
- package/dist/util/git/error.js.map +1 -1
- package/dist/util/host-rules.js +5 -3
- package/dist/util/host-rules.js.map +1 -1
- package/dist/util/http/cache/abstract-http-cache-provider.js +3 -2
- package/dist/util/http/cache/abstract-http-cache-provider.js.map +1 -1
- package/dist/util/http/cache/package-http-cache-provider.js +2 -1
- package/dist/util/http/cache/package-http-cache-provider.js.map +1 -1
- package/dist/util/http/github.js +15 -11
- package/dist/util/http/github.js.map +1 -1
- package/dist/util/http/gitlab.js +5 -4
- package/dist/util/http/gitlab.js.map +1 -1
- package/dist/util/http/http.js +2 -1
- package/dist/util/http/http.js.map +1 -1
- package/dist/util/http/jwt.js +2 -1
- package/dist/util/http/jwt.js.map +1 -1
- package/dist/util/http/retry-after.js +2 -1
- package/dist/util/http/retry-after.js.map +1 -1
- package/dist/util/http/status.js +95 -0
- package/dist/util/http/status.js.map +1 -0
- package/dist/util/merge-confidence/index.js +3 -2
- package/dist/util/merge-confidence/index.js.map +1 -1
- package/dist/util/package-rules/current-version.js +4 -1
- package/dist/util/package-rules/current-version.js.map +1 -1
- package/dist/util/package-rules/index.js +7 -3
- package/dist/util/package-rules/index.js.map +1 -1
- package/dist/util/schema-utils/index.js +5 -0
- package/dist/util/schema-utils/index.js.map +1 -1
- package/dist/workers/global/config/parse/host-rules-from-env.js +2 -1
- package/dist/workers/global/config/parse/host-rules-from-env.js.map +1 -1
- package/dist/workers/repository/common.js +4 -1
- package/dist/workers/repository/common.js.map +1 -1
- package/dist/workers/repository/config-migration/branch/index.js +2 -1
- package/dist/workers/repository/config-migration/branch/index.js.map +1 -1
- package/dist/workers/repository/dependency-dashboard.js +6 -2
- package/dist/workers/repository/dependency-dashboard.js.map +1 -1
- package/dist/workers/repository/finalize/repository-statistics.js +4 -1
- package/dist/workers/repository/finalize/repository-statistics.js.map +1 -1
- package/dist/workers/repository/init/merge.js +13 -3
- package/dist/workers/repository/init/merge.js.map +1 -1
- package/dist/workers/repository/onboarding/branch/check.js +2 -1
- package/dist/workers/repository/onboarding/branch/check.js.map +1 -1
- package/dist/workers/repository/onboarding/pr/pr-list.js +4 -2
- package/dist/workers/repository/onboarding/pr/pr-list.js.map +1 -1
- package/dist/workers/repository/process/extract-update.js +4 -1
- package/dist/workers/repository/process/extract-update.js.map +1 -1
- package/dist/workers/repository/process/lookup/digest.js +2 -1
- package/dist/workers/repository/process/lookup/digest.js.map +1 -1
- package/dist/workers/repository/process/lookup/generate.js +1 -1
- package/dist/workers/repository/process/lookup/generate.js.map +1 -1
- package/dist/workers/repository/process/lookup/index.js +4 -1
- package/dist/workers/repository/process/lookup/index.js.map +1 -1
- package/dist/workers/repository/process/lookup/utils.js +7 -1
- package/dist/workers/repository/process/lookup/utils.js.map +1 -1
- package/dist/workers/repository/process/vulnerabilities.js +10 -3
- package/dist/workers/repository/process/vulnerabilities.js.map +1 -1
- package/dist/workers/repository/reconfigure/index.js +2 -1
- package/dist/workers/repository/reconfigure/index.js.map +1 -1
- package/dist/workers/repository/update/branch/auto-replace.js +6 -2
- package/dist/workers/repository/update/branch/auto-replace.js.map +1 -1
- package/dist/workers/repository/update/branch/errors.js +2 -1
- package/dist/workers/repository/update/branch/errors.js.map +1 -1
- package/dist/workers/repository/update/branch/execute-post-upgrade-commands.js +2 -2
- package/dist/workers/repository/update/branch/execute-post-upgrade-commands.js.map +1 -1
- package/dist/workers/repository/update/branch/get-updated.js +1 -2
- package/dist/workers/repository/update/branch/get-updated.js.map +1 -1
- package/dist/workers/repository/update/branch/index.js +2 -1
- package/dist/workers/repository/update/branch/index.js.map +1 -1
- package/dist/workers/repository/update/branch/status-checks.js +2 -1
- package/dist/workers/repository/update/branch/status-checks.js.map +1 -1
- package/dist/workers/repository/update/pr/body/index.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/release-notes.js +3 -2
- package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
- package/dist/workers/repository/update/pr/index.js +7 -3
- package/dist/workers/repository/update/pr/index.js.map +1 -1
- package/dist/workers/repository/updates/generate.js +6 -3
- package/dist/workers/repository/updates/generate.js.map +1 -1
- package/package.json +2 -2
- package/renovate-schema.json +2 -2
|
@@ -206,6 +206,17 @@ function isWithinHost(matchHost, adminMatchHost) {
|
|
|
206
206
|
const url = parseUrl(matchHost) ? matchHost : `https://${matchHost}`;
|
|
207
207
|
return matchesHost(url, adminMatchHost, { prefixOnly: true });
|
|
208
208
|
}
|
|
209
|
+
function isWithinAdminHost(matchHost, adminHost) {
|
|
210
|
+
return adminHost !== null && isWithinHost(matchHost, adminHost);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Whether the admin granted `allowInternal` for every host `matchHost` can reach. A `null` entry is a grant without host restriction.
|
|
214
|
+
*/
|
|
215
|
+
function isCoveredByAdminHosts(adminHosts, matchHost) {
|
|
216
|
+
if (!adminHosts) return false;
|
|
217
|
+
if (adminHosts.has(null)) return true;
|
|
218
|
+
return !!matchHost && [...adminHosts].some((adminHost) => isWithinAdminHost(matchHost, adminHost));
|
|
219
|
+
}
|
|
209
220
|
/**
|
|
210
221
|
* Migrate a config, tolerating a migration which throws.
|
|
211
222
|
*
|
|
@@ -276,12 +287,11 @@ function withoutAdminSuppliedValues(resolved, admin) {
|
|
|
276
287
|
const adminHosts = admin.headers.get(nameValueIdentity(name, value));
|
|
277
288
|
if (!adminHosts) return true;
|
|
278
289
|
if (adminHosts.has(null)) return false;
|
|
279
|
-
return !(rule.matchHost && [...adminHosts].some((adminHost) =>
|
|
290
|
+
return !(rule.matchHost && [...adminHosts].some((adminHost) => isWithinAdminHost(rule.matchHost, adminHost)));
|
|
280
291
|
}))
|
|
281
292
|
};
|
|
282
293
|
if (!isUndefined(filtered.allowInternal)) {
|
|
283
|
-
|
|
284
|
-
if (adminHosts && (adminHosts.has(null) || !!filtered.matchHost && [...adminHosts].some((adminHost) => adminHost !== null && isWithinHost(filtered.matchHost, adminHost)))) delete filtered.allowInternal;
|
|
294
|
+
if (isCoveredByAdminHosts(admin.internalGrants.get(filtered.allowInternal.toString()), filtered.matchHost)) delete filtered.allowInternal;
|
|
285
295
|
}
|
|
286
296
|
return filtered;
|
|
287
297
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","names":["configValidation.validateConfig","hostRules.matchesHost","presets.resolveConfigPresets"],"sources":["../../../../lib/workers/repository/init/merge.ts"],"sourcesContent":["import {\n isNonEmptyArray,\n isNonEmptyObject,\n isNonEmptyString,\n isString,\n isUndefined,\n} from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { getConfigFileNames } from '../../../config/app-strings.ts';\nimport { decryptConfig } from '../../../config/decrypt.ts';\nimport { mergeChildConfig } from '../../../config/index.ts';\nimport { massageConfig } from '../../../config/massage.ts';\nimport { migrateAndValidate } from '../../../config/migrate-validate.ts';\nimport { migrateConfig } from '../../../config/migration.ts';\nimport { parseFileConfig } from '../../../config/parse.ts';\nimport * as presets from '../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../config/secrets.ts';\nimport type {\n AllConfig,\n MigratedConfig,\n RenovateConfig,\n ValidationMessage,\n} from '../../../config/types.ts';\nimport * as configValidation from '../../../config/validation.ts';\nimport { ConfigValidationTopic } from '../../../config/validation-helpers/types.ts';\nimport {\n CONFIG_VALIDATION,\n REPOSITORY_CHANGED,\n} from '../../../constants/error-messages.ts';\nimport { pkg } from '../../../expose.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as npmApi from '../../../modules/datasource/npm/index.ts';\nimport { platform } from '../../../modules/platform/index.ts';\nimport { scm } from '../../../modules/platform/scm.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { HostRule } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport { clone } from '../../../util/clone.ts';\nimport { getInheritedOrGlobal, parseJson } from '../../../util/common.ts';\nimport { setUserEnv } from '../../../util/env.ts';\nimport { readLocalFile, readSystemFile } from '../../../util/fs/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport * as queue from '../../../util/http/queue.ts';\nimport * as throttle from '../../../util/http/throttle.ts';\nimport { maskToken } from '../../../util/mask.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport { safeStringify } from '../../../util/stringify.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { getOnboardingConfig } from '../onboarding/branch/config.ts';\nimport {\n getOnboardingConfigFromCache,\n getOnboardingFileNameFromCache,\n setOnboardingConfigDetails,\n} from '../onboarding/branch/onboarding-branch-cache.ts';\nimport {\n OnboardingState,\n getDefaultConfigFileName,\n} from '../onboarding/common.ts';\nimport { filterAllowedEnv } from './filter-allowed-env.ts';\nimport type { RepoFileConfig, RepositoryWorkerConfig } from './types.ts';\n\nexport async function detectConfigFile(): Promise<string | null> {\n const fileList = await scm.getFileList();\n for (const fileName of getConfigFileNames()) {\n if (fileName === 'package.json') {\n try {\n const pJson = JSON.parse(\n (await readLocalFile('package.json', 'utf8'))!,\n );\n if (pJson.renovate) {\n logger.warn(\n 'Using package.json for Renovate config is deprecated - please use a dedicated configuration file instead',\n );\n return 'package.json';\n }\n } catch {\n // Do nothing\n }\n } else if (fileList.includes(fileName)) {\n return fileName;\n }\n }\n return null;\n}\n\nexport async function detectRepoFileConfig(\n branchName?: string,\n): Promise<RepoFileConfig> {\n const cache = getCache();\n let { configFileName } = cache;\n if (isNonEmptyString(configFileName)) {\n let configFileRaw: string | null;\n try {\n configFileRaw = await platform.getRawFile(\n configFileName,\n undefined,\n branchName,\n );\n } catch (err) {\n // istanbul ignore if\n if (err instanceof ExternalHostError) {\n throw err;\n }\n configFileRaw = null;\n }\n if (configFileRaw) {\n let configFileParsed = parseJson(configFileRaw, configFileName) as any;\n if (configFileName === 'package.json') {\n configFileParsed = configFileParsed.renovate;\n }\n return { configFileName, configFileParsed };\n }\n logger.debug('Existing config file no longer exists');\n delete cache.configFileName;\n }\n\n if (OnboardingState.onboardingCacheValid) {\n configFileName = getOnboardingFileNameFromCache();\n } else {\n configFileName = coerceString(await detectConfigFile());\n }\n\n if (!configFileName) {\n logger.debug('No renovate config file found');\n cache.configFileName = '';\n return {};\n }\n cache.configFileName = configFileName;\n logger.debug(`Found ${configFileName} config file`);\n // TODO #22198\n let configFileParsed: any;\n let configFileRaw: string | undefined | null;\n\n if (OnboardingState.onboardingCacheValid) {\n const cachedConfig = getOnboardingConfigFromCache();\n const parsedConfig = cachedConfig ? JSON.parse(cachedConfig) : undefined;\n if (parsedConfig) {\n setOnboardingConfigDetails(configFileName, JSON.stringify(parsedConfig));\n return { configFileName, configFileParsed: parsedConfig };\n }\n }\n\n if (configFileName === 'package.json') {\n // We already know it parses\n configFileParsed = JSON.parse(\n // TODO #22198\n (await readLocalFile('package.json', 'utf8'))!,\n ).renovate;\n if (isString(configFileParsed)) {\n logger.debug('Massaging string renovate config to extends array');\n configFileParsed = { extends: [configFileParsed] };\n }\n logger.debug({ config: configFileParsed }, 'package.json>renovate config');\n } else {\n configFileRaw = await readLocalFile(configFileName, 'utf8');\n // istanbul ignore if\n if (!isString(configFileRaw)) {\n logger.warn({ configFileName }, 'Null contents when reading config file');\n throw new Error(REPOSITORY_CHANGED);\n }\n // istanbul ignore if\n if (!configFileRaw.length) {\n configFileRaw = '{}';\n }\n\n const parseResult = parseFileConfig(configFileName, configFileRaw);\n\n if (!parseResult.success) {\n return {\n configFileName,\n configFileParseError: {\n validationError: parseResult.validationError,\n validationMessage: parseResult.validationMessage,\n },\n };\n }\n configFileParsed = parseResult.parsedContents;\n logger.debug(\n { fileName: configFileName, config: configFileParsed },\n 'Repository config',\n );\n }\n\n setOnboardingConfigDetails(configFileName, JSON.stringify(configFileParsed));\n return { configFileName, configFileParsed };\n}\n\nexport function checkForRepoConfigError(repoConfig: RepoFileConfig): void {\n if (!repoConfig.configFileParseError) {\n return;\n }\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = repoConfig.configFileName;\n error.validationError = repoConfig.configFileParseError.validationError;\n error.validationMessage = repoConfig.configFileParseError.validationMessage;\n throw error;\n}\n\n/**\n * Validation source for `repositories[]` object-entry config.\n *\n * As these are managed by the self-hosted admin's global config (`config.js`, or through environment variables, CLI options) we shouldn't report this as an issue the repo owner has introduced.\n */\nconst repositoriesEntrySource = 'Self-hosted config (`repositories[]`)';\n\nconst repoFileValidationError =\n 'The Renovate configuration file contains some invalid settings';\n\nconst repositoriesEntryValidationError =\n 'The self-hosted `repositories[]` config contains some invalid settings';\n\nfunction throwConfigValidationError(\n validationSource: string | undefined,\n errors: ValidationMessage[],\n validationError = repoFileValidationError,\n): never {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = validationSource;\n error.validationError = validationError;\n error.validationMessage = errors.map((e) => e.message).join(', ');\n throw error;\n}\n\n/**\n * Validate a fully-resolved config (i.e. after `resolveConfigPresets`).\n *\n * If there are top-level `allowedEnv`/`allowedHeaders` violations, these are reported with `ConfigValidationTopic.Security` and always fail a validation, as they are sensitive config options that need to be blocked.\n *\n * All other issues will be a WARN, unless `configValidationError=true`, because these are resolved config options and may not be in control of the repository owner.\n *\n * `validationSource` is reported to the user; use `repositoriesEntrySource` and `repositoriesEntryValidationError` for admin-controlled object entries so a fault is not blamed on the repo owner.\n */\nasync function validateResolvedConfig(\n resolved: RenovateConfig,\n validationSource: string | undefined,\n strict: boolean,\n validationError?: string,\n): Promise<void> {\n const { errors, warnings } = await configValidation.validateConfig(\n 'repo',\n // `validateConfig` expects massaged input\n massageConfig(resolved),\n );\n\n // Security findings are collected from the warnings too: `validateConfig` folds the results of the sub-validations it runs (notably `onboardingConfig`) into its warnings, and a finding is no less real for having been reported from within one\n const securityErrors = [...errors, ...warnings].filter(\n (err) => err.topic === ConfigValidationTopic.Security,\n );\n const otherErrors = errors.filter(\n (err) => err.topic !== ConfigValidationTopic.Security,\n );\n const otherWarnings = warnings.filter(\n (err) => err.topic !== ConfigValidationTopic.Security,\n );\n\n // before throwing, make sure that any other errors or warnings are logged, as there may be important findings\n if (otherErrors.length || otherWarnings.length) {\n logger.debug(\n { errors: otherErrors, warnings: otherWarnings },\n 'Config validation failed on resolved config, for non-security-sensitive reasons',\n );\n }\n\n if (securityErrors.length) {\n throwConfigValidationError(\n validationSource,\n securityErrors,\n validationError,\n );\n }\n if (strict && otherErrors.length) {\n throwConfigValidationError(validationSource, otherErrors, validationError);\n }\n}\n\n/**\n * Identify a single `env` variable, or a single header of a host rule, by name and value.\n *\n * As `env` is replaced wholesale and `hostRules` is `mergeable`, self-hosted config and repo config end up indistinguishable in the resolved config, so we need a stable way to look a given name and value up.\n */\nfunction nameValueIdentity(name: string, value: string): string {\n // use safeStringify to avoid any potential for an attacker-controlled value to attempt to try and fake the separator and inject in their value as priority\n return safeStringify([name, value]);\n}\n\n/**\n * Index a set of host rules' headers by {@link nameValueIdentity}, recording the `matchHost` values each is set for (`null` for a host-less rule, which matches every host).\n */\nfunction headersByIdentity(\n rules: HostRule[] | undefined,\n): Map<string, Set<string | null>> {\n const result = new Map<string, Set<string | null>>();\n for (const rule of coerceArray(rules)) {\n for (const [name, value] of Object.entries(coerceObject(rule.headers))) {\n const identity = nameValueIdentity(name, value);\n const hosts = result.get(identity) ?? new Set<string | null>();\n hosts.add(rule.matchHost ?? null);\n result.set(identity, hosts);\n }\n }\n return result;\n}\n\n/**\n * Whether every request matched by `matchHost` is also matched by `adminMatchHost` - i.e. a rule scoped to `matchHost` cannot reach any host the admin's own rule does not already reach.\n *\n * A bare hostname is compared as its `https://` URL. `matchesHost` treats a bare `adminMatchHost` as also covering its subdomains, which errs on the admin-friendly side: those hosts sit within the admin's own domain.\n */\nfunction isWithinHost(matchHost: string, adminMatchHost: string): boolean {\n const url = parseUrl(matchHost) ? matchHost : `https://${matchHost}`;\n // by prefix only: a `matchHost` such as `https://host/path` reaches `https://host/path-other/` as well, which the admin's `https://host/path/` does not\n return hostRules.matchesHost(url, adminMatchHost, { prefixOnly: true });\n}\n\n/**\n * Migrate a config, tolerating a migration which throws.\n *\n * `hostRules` migration throws when a rule carries more than one host-matching field. That is per-rule invalid config which {@link applyHostRules} logs and skips over, keeping the rest of the run going, so migrating a whole config here must not escalate it into an error which aborts the repository.\n */\nfunction migrateConfigOrWarn(config: RenovateConfig): MigratedConfig {\n try {\n return migrateConfig(config);\n } catch (err) {\n logger.warn({ err }, 'Error migrating config');\n return { isMigrated: false, migratedConfig: config };\n }\n}\n\n/**\n * The security-sensitive values (`env`, and `hostRules[].headers`) the self-hosted admin supplied, indexed by {@link nameValueIdentity}; the headers additionally record the `matchHost` values each was set for.\n *\n * `mergeChildConfig` promotes `force` values to the top level, so each config contributes its `force` alongside its top-level values.\n */\ninterface AdminSuppliedValues {\n env: Set<string>;\n headers: Map<string, Set<string | null>>;\n /** the `allowInternal` values ('true'/'false') the admin set, recording the `matchHost` values each is set for (`null` for a host-less rule) */\n internalGrants: Map<string, Set<string | null>>;\n}\n\n/**\n * Migrate a set of host rules, so that their `matchHost` compares like for like against the resolved config's own: migration rewrites them (e.g. a legacy `hostName` becoming a `matchHost`, or a bare `matchHost` gaining a scheme), and the resolved config only ever contains the migrated spellings.\n */\nfunction migratedHostRules(rules: HostRule[] | undefined): HostRule[] {\n if (!isNonEmptyArray(rules)) {\n return [];\n }\n return coerceArray(\n migrateConfigOrWarn({ hostRules: rules }).migratedConfig.hostRules,\n );\n}\n\n/**\n * Collect the {@link AdminSuppliedValues} of every config the self-hosted admin supplied.\n *\n * A preset is only ever resolved into the config which extends it, so a config here is the *resolved* form of an admin config: whatever the presets the admin chose to extend contribute is as much theirs as a value they wrote inline.\n */\nfunction adminSuppliedValues(\n adminConfigs: RenovateConfig[],\n): AdminSuppliedValues {\n const env = new Set<string>();\n const headers = new Map<string, Set<string | null>>();\n const internalGrants = new Map<string, Set<string | null>>();\n\n for (const adminConfig of adminConfigs) {\n for (const source of [adminConfig, adminConfig.force]) {\n for (const [name, value] of Object.entries(coerceObject(source?.env))) {\n env.add(nameValueIdentity(name, value));\n }\n const rules = migratedHostRules(source?.hostRules);\n for (const [identity, matchHosts] of headersByIdentity(rules)) {\n const hosts = headers.get(identity) ?? new Set<string | null>();\n for (const matchHost of matchHosts) {\n hosts.add(matchHost);\n }\n headers.set(identity, hosts);\n }\n for (const rule of rules) {\n if (!isUndefined(rule.allowInternal)) {\n const key = rule.allowInternal.toString();\n const hosts = internalGrants.get(key) ?? new Set<string | null>();\n hosts.add(rule.matchHost ?? null);\n internalGrants.set(key, hosts);\n }\n }\n }\n }\n\n return { env, headers, internalGrants };\n}\n\n/**\n * Return `resolved` without the security-sensitive (`env` and `hostRules[].headers`) values the self-hosted admin supplied themselves.\n *\n * `allowedEnv`/`allowedHeaders` exist to constrain what repository config, and the presets it extends, may inject; the self-hosted admin is who sets those allowlists, so their own values are not violations of them.\n *\n * Reporting them would abort the repository and file a \"Fix Renovate Configuration\" issue whose cause the repository's owners can neither see nor fix.\n */\nfunction withoutAdminSuppliedValues(\n resolved: RenovateConfig,\n admin: AdminSuppliedValues,\n): RenovateConfig {\n const result = { ...resolved };\n\n if (result.env) {\n result.env = Object.fromEntries(\n Object.entries(result.env).filter(\n ([name, value]) => !admin.env.has(nameValueIdentity(name, value)),\n ),\n );\n }\n\n // A header is the admin's own when its name and value match one the admin set for hosts that already cover this rule's hosts - the exact `matchHost` spelling must not matter, as migration and presets can re-spell (e.g. add a scheme) or narrow (e.g. a subpath) it\n if (result.hostRules) {\n result.hostRules = result.hostRules.map((rule) => {\n const filtered: HostRule = {\n ...rule,\n headers: Object.fromEntries(\n Object.entries(coerceObject(rule.headers)).filter(([name, value]) => {\n const adminHosts = admin.headers.get(\n nameValueIdentity(name, value),\n );\n if (!adminHosts) {\n // not a header the admin set - report it\n return true;\n }\n if (adminHosts.has(null)) {\n // the admin already sends it to every host\n return false;\n }\n // a host-less rule reaches every host, so only a host-less admin header (above) can exempt it\n return !(\n rule.matchHost &&\n [...adminHosts].some(\n (adminHost) =>\n adminHost !== null &&\n isWithinHost(rule.matchHost!, adminHost),\n )\n );\n }),\n ),\n };\n\n // same principle for `allowInternal`: the admin's own value, for hosts their own rules already cover, is not a violation\n if (!isUndefined(filtered.allowInternal)) {\n const adminHosts = admin.internalGrants.get(\n filtered.allowInternal.toString(),\n );\n const covered =\n adminHosts &&\n (adminHosts.has(null) ||\n (!!filtered.matchHost &&\n [...adminHosts].some(\n (adminHost) =>\n adminHost !== null &&\n isWithinHost(filtered.matchHost!, adminHost),\n )));\n if (covered) {\n delete filtered.allowInternal;\n }\n }\n\n return filtered;\n });\n }\n\n // `mergeChildConfig` promotes `force` values into the config it returns, so the admin's own `force.env`/`force.hostRules[].headers` are applied - and exempted - the same way their top-level equivalents are\n if (result.force) {\n result.force = withoutAdminSuppliedValues(result.force, admin);\n }\n\n return result;\n}\n\n// Check for repository config\nexport async function mergeRenovateConfig(\n config: RepositoryWorkerConfig,\n branchName?: string,\n): Promise<RenovateConfig> {\n let returnConfig: RepositoryWorkerConfig = { ...config };\n let repoConfig: RepoFileConfig = {};\n if (getInheritedOrGlobal('requireConfig') !== 'ignored') {\n repoConfig = await detectRepoFileConfig(branchName);\n }\n if (!repoConfig.configFileParsed && config.mode === 'silent') {\n logger.debug(\n 'When mode=silent and repo has no config file, we use the onboarding config as repo config',\n );\n const configFileName = getDefaultConfigFileName();\n repoConfig = {\n configFileName,\n configFileParsed: await getOnboardingConfig(config),\n };\n }\n const configFileParsed = coerceObject(repoConfig?.configFileParsed);\n const resolvedRepoConfig = await resolveStaticRepoConfig(\n configFileParsed,\n process.env.RENOVATE_X_STATIC_REPO_CONFIG_FILE,\n );\n\n // Apply the repositories[] object-entry config between global config and\n // repository file config.\n // Must run after repository file config is loaded so its `ignorePresets` can\n // be included when resolving object-entry presets.\n const repoEntryConfig = returnConfig.repositoryEntryConfig;\n delete returnConfig.repositoryEntryConfig;\n\n // The presets the self-hosted admin's own config extends are their config too - a repository which merely inherits them must neither be blamed for what they contribute, nor have it filtered out from under it.\n // They are resolved separately because below they are resolved together with the repository's own presets, leaving no way to tell one from the other; a failure here is left to that resolution to report, as it is the one whose result is used.\n let adminPresetConfig: AllConfig = {};\n if (isNonEmptyArray(returnConfig.extends)) {\n try {\n ({ config: adminPresetConfig } = await presets.resolveConfigPresets(\n { extends: returnConfig.extends },\n config,\n config.ignorePresets,\n ));\n } catch (err) {\n logger.debug(\n { err },\n 'Error resolving the self-hosted config presets - continuing without their exemption',\n );\n }\n }\n\n // self-hosted configuration is always allowed\n // `force.env` is included because `mergeChildConfig` promotes `force` values to the top level as configs are merged\n const adminSuppliedEnv = {\n // presets the admin extends: as much theirs as anything they set inline, which is why they are listed first - the values they set themselves win\n ...coerceObject(adminPresetConfig.env),\n ...coerceObject(adminPresetConfig.force?.env),\n // `env` settings the self-hosted admin supplied (via `config.js`, etc), `env`, etc\n ...coerceObject(config.env),\n ...coerceObject(config.force?.env),\n // `repositories[]` entry for this repo - refreshed with the resolved values below, once its own presets, secrets and variables have been applied\n ...coerceObject(repoEntryConfig?.env),\n ...coerceObject(repoEntryConfig?.force?.env),\n };\n\n // every config the self-hosted admin supplied, in resolved form, for {@link adminSuppliedValues}\n const adminConfigs: RenovateConfig[] = [config, adminPresetConfig];\n\n if (isNonEmptyObject(repoEntryConfig)) {\n const repoEntry = repoEntryConfig as RenovateConfig;\n const toResolve: RenovateConfig = {\n ...repoEntry,\n extends: [\n ...coerceArray(returnConfig.extends),\n ...coerceArray(repoEntry.extends),\n ],\n ignorePresets: [\n ...coerceArray(returnConfig.ignorePresets),\n ...coerceArray(repoEntry.ignorePresets),\n ...coerceArray(resolvedRepoConfig.ignorePresets),\n ],\n };\n delete returnConfig.extends;\n\n let { config: resolvedRepoEntry } = await presets.resolveConfigPresets(\n toResolve,\n config,\n );\n\n // Migrate before validating so legacy option names contributed by the entry or its presets are migrated rather than reported as invalid options.\n const entryMigration = migrateConfigOrWarn(resolvedRepoEntry);\n if (entryMigration.isMigrated) {\n resolvedRepoEntry = entryMigration.migratedConfig;\n }\n\n // Migrate the entry's own config the same way, so its values compare like for like below: migration can rewrite them (e.g. a legacy `hostName` becoming a `matchHost`, or a bare `matchHost` gaining a scheme), and the resolved config only ever contains the migrated spellings\n const { migratedConfig: migratedEntry } = migrateConfigOrWarn(toResolve);\n // `resolveConfigPresets` removes both of these from its result\n delete migratedEntry.extends;\n delete migratedEntry.ignorePresets;\n\n // The entry, and every preset it extends, is the self-hosted admin's own config, so its `env`/`headers` are exempt from the allowlists the admin set - but the rest of the resolved result is still worth validating before any of it is applied (npmrc, hostRules, env).\n // When resolution and migration changed nothing, the presets contributed nothing and the entry itself was already validated as part of the admin's global config, so skip the (costly) validation walk entirely.\n adminConfigs.push(resolvedRepoEntry);\n if (!dequal(resolvedRepoEntry, migratedEntry)) {\n await validateResolvedConfig(\n withoutAdminSuppliedValues(\n resolvedRepoEntry,\n adminSuppliedValues(adminConfigs),\n ),\n repositoriesEntrySource,\n config.configValidationError === true,\n repositoriesEntryValidationError,\n );\n }\n\n applyNpmrc(resolvedRepoEntry, 'resolvedRepoEntry');\n\n const resolvedRepoEntryWithSecrets = applySecretsAndVariablesToConfig({\n config: resolvedRepoEntry,\n // like the repository config below, the entry can carry its own `secrets`/`variables` - `validateConfigSecretsAndVariables` validates them at startup\n secrets: mergeChildConfig(\n coerceObject(config.secrets),\n coerceObject(resolvedRepoEntry.secrets),\n ),\n variables: mergeChildConfig(\n coerceObject(config.variables),\n coerceObject(resolvedRepoEntry.variables),\n ),\n });\n\n // Refresh the admin-supplied snapshot from the resolved entry: it also carries whatever the presets the entry extends contributed, and its `env` values may contain `{{ secrets.* }}`/`{{ variables.* }}` templates only interpolated here - e.g. when the secrets are defined on the entry itself rather than globally.\n // Interpolation is recursive, so the interpolated `force.env` values stay nested under `force`.\n Object.assign(\n adminSuppliedEnv,\n coerceObject(resolvedRepoEntryWithSecrets.env),\n coerceObject(resolvedRepoEntryWithSecrets.force?.env),\n );\n\n // the `repositories[]` entry is the self-hosted admin's own config - as its `env` is already treated as admin-supplied, its rules are `trusted` too, so that an admin can still override a header they set globally for just this repository\n applyHostRules(resolvedRepoEntryWithSecrets, { trusted: true });\n returnConfig = mergeChildConfig(returnConfig, resolvedRepoEntryWithSecrets);\n }\n\n if (isNonEmptyArray(returnConfig.extends)) {\n resolvedRepoConfig.extends = [\n ...coerceArray(returnConfig.extends),\n ...coerceArray(resolvedRepoConfig.extends),\n ];\n delete returnConfig.extends;\n }\n checkForRepoConfigError(repoConfig);\n const migratedConfig = await migrateAndValidate(config, resolvedRepoConfig);\n if (migratedConfig.errors?.length) {\n throwConfigValidationError(\n repoConfig.configFileName,\n migratedConfig.errors,\n );\n }\n // v8 ignore else -- migration always leaves a warnings array behind\n if (migratedConfig.warnings) {\n returnConfig.warnings = [\n ...coerceArray(returnConfig.warnings),\n ...migratedConfig.warnings,\n ];\n }\n delete migratedConfig.errors;\n delete migratedConfig.warnings;\n // TODO #22198\n const repository = config.repository!;\n // Decrypt before resolving in case we need npm authentication for any presets\n const decryptedConfig = await decryptConfig(migratedConfig, repository);\n applyNpmrc(decryptedConfig, 'decrypted');\n\n // NOTE that this should not be used with any other configuration (`resolvedConfig`, etc) below, as they will include addditionally merged configuration\n // Decrypted secrets are sanitised, so should be safe to log\n await logShallowConfig(decryptedConfig, config);\n\n // Decrypt after resolving in case the preset contains npm authentication instead\n const { config: configToDecrypt } = await presets.resolveConfigPresets(\n decryptedConfig,\n config,\n config.ignorePresets,\n );\n let resolvedConfig = await decryptConfig(configToDecrypt, repository);\n logger.trace({ config: resolvedConfig }, 'resolved config');\n const migrationResult = migrateConfig(resolvedConfig);\n if (migrationResult.isMigrated) {\n logger.debug('Resolved config needs migrating');\n logger.trace({ config: resolvedConfig }, 'resolved config after migrating');\n resolvedConfig = migrationResult.migratedConfig;\n }\n\n // Validate the fully-resolved repository config, enforcing validation is applied against all stages of the preset, and providing defence-in-depth for any sensitive config options\n // note that we do not need to re-run `migrateAndValidate` if we're already at the same configuration that we've previously resolved, decrypted and migrated, so we can avoid a costly re-validation\n if (!dequal(resolvedConfig, migratedConfig)) {\n await validateResolvedConfig(\n // the admin's own `extends` are resolved into this config alongside the repository's, so exempt what they contributed: the repository can neither see nor fix it\n withoutAdminSuppliedValues(\n resolvedConfig,\n adminSuppliedValues(adminConfigs),\n ),\n // a repository that is not yet onboarded has no config file to blame; 'config' mirrors other unattributable validation errors (e.g. `decryptConfig`)\n repoConfig.configFileName ?? 'config',\n config.configValidationError === true,\n );\n }\n if (isString(resolvedConfig.npmrc)) {\n logger.debug(\n 'Ignoring any .npmrc files in repository due to configured npmrc',\n );\n }\n applyNpmrc(resolvedConfig, 'resolved');\n resolvedConfig = applySecretsAndVariablesToConfig({\n config: resolvedConfig,\n secrets: mergeChildConfig(\n coerceObject(config.secrets),\n coerceObject(resolvedConfig.secrets),\n ),\n variables: mergeChildConfig(\n coerceObject(config.variables),\n coerceObject(resolvedConfig.variables),\n ),\n });\n\n applyHostRules(resolvedConfig);\n returnConfig = mergeChildConfig(returnConfig, resolvedConfig);\n ({ config: returnConfig } = await presets.resolveConfigPresets(\n returnConfig,\n config,\n ));\n returnConfig.renovateJsonPresent = true;\n // istanbul ignore if\n if (returnConfig.ignorePaths?.length) {\n logger.debug(\n { ignorePaths: returnConfig.ignorePaths },\n `Found repo ignorePaths`,\n );\n }\n\n setUserEnv(filterAllowedEnv(returnConfig.env, adminSuppliedEnv));\n delete returnConfig.env;\n\n return returnConfig;\n}\n\nexport function applyNpmrc(\n config: RenovateConfig,\n configType?: 'resolved' | 'resolvedRepoEntry' | 'decrypted',\n): void {\n setNpmTokenInNpmrc(config);\n if (!isString(config.npmrc)) {\n return;\n }\n logger.debug(\n `Setting npmrc from ${configType ? `${configType} ` : ''}config`,\n );\n npmApi.setNpmrc(config.npmrc);\n}\n\nexport function applyHostRules(\n config: RenovateConfig,\n options?: hostRules.AddHostRuleOptions,\n): void {\n if (!config.hostRules) {\n return;\n }\n\n logger.debug('Setting hostRules from config');\n // `hostRules.add` enforces `allowedHeaders` on every untrusted rule it registers - a `trusted` rule (see `options`) is exempt\n for (const rule of config.hostRules) {\n try {\n hostRules.add(rule, options);\n } catch (err) {\n logger.warn({ err, config: rule }, 'Error setting hostRule from config');\n }\n }\n // host rules can change concurrency\n queue.clear();\n throttle.clear();\n delete config.hostRules;\n}\n\n/** needed when using portal secrets for npmToken */\nexport function setNpmTokenInNpmrc(config: RenovateConfig): void {\n if (!isString(config.npmToken)) {\n return;\n }\n\n const token = config.npmToken;\n logger.debug({ npmToken: maskToken(token) }, 'Migrating npmToken to npmrc');\n\n if (!isString(config.npmrc)) {\n logger.debug('Adding npmrc to config');\n config.npmrc = `//registry.npmjs.org/:_authToken=${token}\\n`;\n delete config.npmToken;\n return;\n }\n\n if (config.npmrc.includes(`\\${NPM_TOKEN}`)) {\n logger.debug(`Replacing \\${NPM_TOKEN} with npmToken`);\n config.npmrc = config.npmrc.replace(regEx(/\\${NPM_TOKEN}/g), token);\n } else {\n logger.debug('Appending _authToken= to end of existing npmrc');\n config.npmrc = config.npmrc.replace(\n regEx(/\\n?$/),\n `\\n_authToken=${token}\\n`,\n );\n }\n\n delete config.npmToken;\n}\n\nexport async function resolveStaticRepoConfig(\n config: AllConfig,\n filename: string | undefined,\n): Promise<AllConfig> {\n if (!isNonEmptyString(filename)) {\n return config;\n }\n\n let staticRepoConfig: AllConfig;\n\n try {\n staticRepoConfig = await tryReadStaticRepoFileConfig(filename);\n } catch (err) {\n logger.fatal({ err }, 'Failed to load static repository config file');\n process.exit(1);\n }\n\n if (!isNonEmptyObject(staticRepoConfig)) {\n return config;\n }\n\n return mergeStaticConfig(config, staticRepoConfig);\n}\n\nexport async function tryReadStaticRepoFileConfig(\n staticRepoConfigFile: string,\n): Promise<AllConfig> {\n logger.debug(`Reading static repo config file from ${staticRepoConfigFile}`);\n\n let staticRepoConfigRaw: string;\n try {\n staticRepoConfigRaw = await readSystemFile(staticRepoConfigFile, 'utf8');\n } catch (err) {\n throw new Error(\n `Failed to read static repo config file: \"${staticRepoConfigFile}\"`,\n { cause: err },\n );\n }\n\n const staticRepoConfig = parseJson(\n staticRepoConfigRaw,\n staticRepoConfigFile,\n ) as AllConfig;\n\n // validate and log issues here to preserve context, caller handles migration and full validation.\n const { errors, warnings } = await configValidation.validateConfig(\n 'repo',\n // `validateConfig` expects massaged input\n massageConfig(staticRepoConfig),\n );\n\n if (isNonEmptyArray(errors) || isNonEmptyArray(warnings)) {\n logger.info(\n { errors, warnings },\n 'Static repo config validation issues detected',\n );\n } else {\n logger.debug(\n { staticRepoConfig },\n 'Static repository config file successfully parsed and validated',\n );\n }\n\n return staticRepoConfig;\n}\n\nexport function mergeStaticConfig(\n config: AllConfig,\n staticRepoConfig: AllConfig,\n): AllConfig {\n // merge extends\n if (isNonEmptyArray(staticRepoConfig.extends)) {\n config.extends = [\n ...staticRepoConfig.extends,\n ...coerceArray(config.extends),\n ];\n delete staticRepoConfig.extends;\n }\n\n // renovate repo config overrides RENOVATE_STATIC_REPO_CONFIG[_FILE]\n return mergeChildConfig(staticRepoConfig, config);\n}\n\n/**\n * Resolve everything but internal Renovate presets and log it out.\n *\n* This allows users to understand the fully resolved configuration, including any `github>`, `local>`, etc presets, but excluding anything that's internal to Renovate (which can be verbose and/or less relevant), and provides useful output for debugging purposes.\n\n* This is also known as the \"shallow\" config.\n\n* Due to caching, this doesn't add any additional requests.\n */\nasync function logShallowConfig(\n _decryptedConfig: RenovateConfig,\n _config: RepositoryWorkerConfig,\n): Promise<void> {\n // make sure we clone the existing config, so we don't modify the existing settings when resolving this in a shallow fashion\n const decryptedConfig = clone(_decryptedConfig);\n const config = clone(_config);\n\n const { config: resolvedConfig, visitedPresets } =\n await presets.resolveConfigPresets(\n clone(decryptedConfig),\n clone(config),\n config.ignorePresets,\n [],\n false,\n );\n logger.debug(\n {\n renovateVersion: pkg.version,\n config: resolvedConfig,\n visitedPresets,\n },\n 'Resolved shallow config, without merging internal presets',\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"merge.js","names":["configValidation.validateConfig","hostRules.matchesHost","presets.resolveConfigPresets"],"sources":["../../../../lib/workers/repository/init/merge.ts"],"sourcesContent":["import {\n isNonEmptyArray,\n isNonEmptyObject,\n isNonEmptyString,\n isString,\n isUndefined,\n} from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { getConfigFileNames } from '../../../config/app-strings.ts';\nimport { decryptConfig } from '../../../config/decrypt.ts';\nimport { mergeChildConfig } from '../../../config/index.ts';\nimport { massageConfig } from '../../../config/massage.ts';\nimport { migrateAndValidate } from '../../../config/migrate-validate.ts';\nimport { migrateConfig } from '../../../config/migration.ts';\nimport { parseFileConfig } from '../../../config/parse.ts';\nimport * as presets from '../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../config/secrets.ts';\nimport type {\n AllConfig,\n MigratedConfig,\n RenovateConfig,\n ValidationMessage,\n} from '../../../config/types.ts';\nimport * as configValidation from '../../../config/validation.ts';\nimport { ConfigValidationTopic } from '../../../config/validation-helpers/types.ts';\nimport {\n CONFIG_VALIDATION,\n REPOSITORY_CHANGED,\n} from '../../../constants/error-messages.ts';\nimport { pkg } from '../../../expose.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as npmApi from '../../../modules/datasource/npm/index.ts';\nimport { platform } from '../../../modules/platform/index.ts';\nimport { scm } from '../../../modules/platform/scm.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { HostRule } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport { clone } from '../../../util/clone.ts';\nimport { getInheritedOrGlobal, parseJson } from '../../../util/common.ts';\nimport { setUserEnv } from '../../../util/env.ts';\nimport { readLocalFile, readSystemFile } from '../../../util/fs/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport * as queue from '../../../util/http/queue.ts';\nimport * as throttle from '../../../util/http/throttle.ts';\nimport { maskToken } from '../../../util/mask.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport { safeStringify } from '../../../util/stringify.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { getOnboardingConfig } from '../onboarding/branch/config.ts';\nimport {\n getOnboardingConfigFromCache,\n getOnboardingFileNameFromCache,\n setOnboardingConfigDetails,\n} from '../onboarding/branch/onboarding-branch-cache.ts';\nimport {\n OnboardingState,\n getDefaultConfigFileName,\n} from '../onboarding/common.ts';\nimport { filterAllowedEnv } from './filter-allowed-env.ts';\nimport type { RepoFileConfig, RepositoryWorkerConfig } from './types.ts';\n\nexport async function detectConfigFile(): Promise<string | null> {\n const fileList = await scm.getFileList();\n for (const fileName of getConfigFileNames()) {\n if (fileName === 'package.json') {\n try {\n const pJson = JSON.parse(\n (await readLocalFile('package.json', 'utf8'))!,\n );\n if (pJson.renovate) {\n logger.warn(\n 'Using package.json for Renovate config is deprecated - please use a dedicated configuration file instead',\n );\n return 'package.json';\n }\n } catch {\n // Do nothing\n }\n } else if (fileList.includes(fileName)) {\n return fileName;\n }\n }\n return null;\n}\n\nexport async function detectRepoFileConfig(\n branchName?: string,\n): Promise<RepoFileConfig> {\n const cache = getCache();\n let { configFileName } = cache;\n if (isNonEmptyString(configFileName)) {\n let configFileRaw: string | null;\n try {\n configFileRaw = await platform.getRawFile(\n configFileName,\n undefined,\n branchName,\n );\n } catch (err) {\n // istanbul ignore if\n if (err instanceof ExternalHostError) {\n throw err;\n }\n configFileRaw = null;\n }\n if (configFileRaw) {\n let configFileParsed = parseJson(configFileRaw, configFileName) as any;\n if (configFileName === 'package.json') {\n configFileParsed = configFileParsed.renovate;\n }\n return { configFileName, configFileParsed };\n }\n logger.debug('Existing config file no longer exists');\n delete cache.configFileName;\n }\n\n if (OnboardingState.onboardingCacheValid) {\n configFileName = getOnboardingFileNameFromCache();\n } else {\n configFileName = coerceString(await detectConfigFile());\n }\n\n if (!configFileName) {\n logger.debug('No renovate config file found');\n cache.configFileName = '';\n return {};\n }\n cache.configFileName = configFileName;\n logger.debug(`Found ${configFileName} config file`);\n // TODO #22198\n let configFileParsed: any;\n let configFileRaw: string | undefined | null;\n\n if (OnboardingState.onboardingCacheValid) {\n const cachedConfig = getOnboardingConfigFromCache();\n const parsedConfig = cachedConfig ? JSON.parse(cachedConfig) : undefined;\n if (parsedConfig) {\n setOnboardingConfigDetails(configFileName, JSON.stringify(parsedConfig));\n return { configFileName, configFileParsed: parsedConfig };\n }\n }\n\n if (configFileName === 'package.json') {\n // We already know it parses\n configFileParsed = JSON.parse(\n // TODO #22198\n (await readLocalFile('package.json', 'utf8'))!,\n ).renovate;\n if (isString(configFileParsed)) {\n logger.debug('Massaging string renovate config to extends array');\n configFileParsed = { extends: [configFileParsed] };\n }\n logger.debug({ config: configFileParsed }, 'package.json>renovate config');\n } else {\n configFileRaw = await readLocalFile(configFileName, 'utf8');\n // istanbul ignore if\n if (!isString(configFileRaw)) {\n logger.warn({ configFileName }, 'Null contents when reading config file');\n throw new Error(REPOSITORY_CHANGED);\n }\n // istanbul ignore if\n if (!configFileRaw.length) {\n configFileRaw = '{}';\n }\n\n const parseResult = parseFileConfig(configFileName, configFileRaw);\n\n if (!parseResult.success) {\n return {\n configFileName,\n configFileParseError: {\n validationError: parseResult.validationError,\n validationMessage: parseResult.validationMessage,\n },\n };\n }\n configFileParsed = parseResult.parsedContents;\n logger.debug(\n { fileName: configFileName, config: configFileParsed },\n 'Repository config',\n );\n }\n\n setOnboardingConfigDetails(configFileName, JSON.stringify(configFileParsed));\n return { configFileName, configFileParsed };\n}\n\nexport function checkForRepoConfigError(repoConfig: RepoFileConfig): void {\n if (!repoConfig.configFileParseError) {\n return;\n }\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = repoConfig.configFileName;\n error.validationError = repoConfig.configFileParseError.validationError;\n error.validationMessage = repoConfig.configFileParseError.validationMessage;\n throw error;\n}\n\n/**\n * Validation source for `repositories[]` object-entry config.\n *\n * As these are managed by the self-hosted admin's global config (`config.js`, or through environment variables, CLI options) we shouldn't report this as an issue the repo owner has introduced.\n */\nconst repositoriesEntrySource = 'Self-hosted config (`repositories[]`)';\n\nconst repoFileValidationError =\n 'The Renovate configuration file contains some invalid settings';\n\nconst repositoriesEntryValidationError =\n 'The self-hosted `repositories[]` config contains some invalid settings';\n\nfunction throwConfigValidationError(\n validationSource: string | undefined,\n errors: ValidationMessage[],\n validationError = repoFileValidationError,\n): never {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = validationSource;\n error.validationError = validationError;\n error.validationMessage = errors.map((e) => e.message).join(', ');\n throw error;\n}\n\n/**\n * Validate a fully-resolved config (i.e. after `resolveConfigPresets`).\n *\n * If there are top-level `allowedEnv`/`allowedHeaders` violations, these are reported with `ConfigValidationTopic.Security` and always fail a validation, as they are sensitive config options that need to be blocked.\n *\n * All other issues will be a WARN, unless `configValidationError=true`, because these are resolved config options and may not be in control of the repository owner.\n *\n * `validationSource` is reported to the user; use `repositoriesEntrySource` and `repositoriesEntryValidationError` for admin-controlled object entries so a fault is not blamed on the repo owner.\n */\nasync function validateResolvedConfig(\n resolved: RenovateConfig,\n validationSource: string | undefined,\n strict: boolean,\n validationError?: string,\n): Promise<void> {\n const { errors, warnings } = await configValidation.validateConfig(\n 'repo',\n // `validateConfig` expects massaged input\n massageConfig(resolved),\n );\n\n // Security findings are collected from the warnings too: `validateConfig` folds the results of the sub-validations it runs (notably `onboardingConfig`) into its warnings, and a finding is no less real for having been reported from within one\n const securityErrors = [...errors, ...warnings].filter(\n (err) => err.topic === ConfigValidationTopic.Security,\n );\n const otherErrors = errors.filter(\n (err) => err.topic !== ConfigValidationTopic.Security,\n );\n const otherWarnings = warnings.filter(\n (err) => err.topic !== ConfigValidationTopic.Security,\n );\n\n // before throwing, make sure that any other errors or warnings are logged, as there may be important findings\n if (otherErrors.length || otherWarnings.length) {\n logger.debug(\n { errors: otherErrors, warnings: otherWarnings },\n 'Config validation failed on resolved config, for non-security-sensitive reasons',\n );\n }\n\n if (securityErrors.length) {\n throwConfigValidationError(\n validationSource,\n securityErrors,\n validationError,\n );\n }\n if (strict && otherErrors.length) {\n throwConfigValidationError(validationSource, otherErrors, validationError);\n }\n}\n\n/**\n * Identify a single `env` variable, or a single header of a host rule, by name and value.\n *\n * As `env` is replaced wholesale and `hostRules` is `mergeable`, self-hosted config and repo config end up indistinguishable in the resolved config, so we need a stable way to look a given name and value up.\n */\nfunction nameValueIdentity(name: string, value: string): string {\n // use safeStringify to avoid any potential for an attacker-controlled value to attempt to try and fake the separator and inject in their value as priority\n return safeStringify([name, value]);\n}\n\n/**\n * Index a set of host rules' headers by {@link nameValueIdentity}, recording the `matchHost` values each is set for (`null` for a host-less rule, which matches every host).\n */\nfunction headersByIdentity(\n rules: HostRule[] | undefined,\n): Map<string, Set<string | null>> {\n const result = new Map<string, Set<string | null>>();\n for (const rule of coerceArray(rules)) {\n for (const [name, value] of Object.entries(coerceObject(rule.headers))) {\n const identity = nameValueIdentity(name, value);\n const hosts = result.get(identity) ?? new Set<string | null>();\n hosts.add(rule.matchHost ?? null);\n result.set(identity, hosts);\n }\n }\n return result;\n}\n\n/**\n * Whether every request matched by `matchHost` is also matched by `adminMatchHost` - i.e. a rule scoped to `matchHost` cannot reach any host the admin's own rule does not already reach.\n *\n * A bare hostname is compared as its `https://` URL. `matchesHost` treats a bare `adminMatchHost` as also covering its subdomains, which errs on the admin-friendly side: those hosts sit within the admin's own domain.\n */\nfunction isWithinHost(matchHost: string, adminMatchHost: string): boolean {\n const url = parseUrl(matchHost) ? matchHost : `https://${matchHost}`;\n // by prefix only: a `matchHost` such as `https://host/path` reaches `https://host/path-other/` as well, which the admin's `https://host/path/` does not\n return hostRules.matchesHost(url, adminMatchHost, { prefixOnly: true });\n}\n\nfunction isWithinAdminHost(\n matchHost: string,\n adminHost: string | null,\n): boolean {\n return adminHost !== null && isWithinHost(matchHost, adminHost);\n}\n\n/**\n * Whether the admin granted `allowInternal` for every host `matchHost` can reach. A `null` entry is a grant without host restriction.\n */\nfunction isCoveredByAdminHosts(\n adminHosts: Set<string | null> | undefined,\n matchHost: string | undefined,\n): boolean {\n if (!adminHosts) {\n return false;\n }\n if (adminHosts.has(null)) {\n return true;\n }\n return (\n !!matchHost &&\n [...adminHosts].some((adminHost) => isWithinAdminHost(matchHost, adminHost))\n );\n}\n\n/**\n * Migrate a config, tolerating a migration which throws.\n *\n * `hostRules` migration throws when a rule carries more than one host-matching field. That is per-rule invalid config which {@link applyHostRules} logs and skips over, keeping the rest of the run going, so migrating a whole config here must not escalate it into an error which aborts the repository.\n */\nfunction migrateConfigOrWarn(config: RenovateConfig): MigratedConfig {\n try {\n return migrateConfig(config);\n } catch (err) {\n logger.warn({ err }, 'Error migrating config');\n return { isMigrated: false, migratedConfig: config };\n }\n}\n\n/**\n * The security-sensitive values (`env`, and `hostRules[].headers`) the self-hosted admin supplied, indexed by {@link nameValueIdentity}; the headers additionally record the `matchHost` values each was set for.\n *\n * `mergeChildConfig` promotes `force` values to the top level, so each config contributes its `force` alongside its top-level values.\n */\ninterface AdminSuppliedValues {\n env: Set<string>;\n headers: Map<string, Set<string | null>>;\n /** the `allowInternal` values ('true'/'false') the admin set, recording the `matchHost` values each is set for (`null` for a host-less rule) */\n internalGrants: Map<string, Set<string | null>>;\n}\n\n/**\n * Migrate a set of host rules, so that their `matchHost` compares like for like against the resolved config's own: migration rewrites them (e.g. a legacy `hostName` becoming a `matchHost`, or a bare `matchHost` gaining a scheme), and the resolved config only ever contains the migrated spellings.\n */\nfunction migratedHostRules(rules: HostRule[] | undefined): HostRule[] {\n if (!isNonEmptyArray(rules)) {\n return [];\n }\n return coerceArray(\n migrateConfigOrWarn({ hostRules: rules }).migratedConfig.hostRules,\n );\n}\n\n/**\n * Collect the {@link AdminSuppliedValues} of every config the self-hosted admin supplied.\n *\n * A preset is only ever resolved into the config which extends it, so a config here is the *resolved* form of an admin config: whatever the presets the admin chose to extend contribute is as much theirs as a value they wrote inline.\n */\nfunction adminSuppliedValues(\n adminConfigs: RenovateConfig[],\n): AdminSuppliedValues {\n const env = new Set<string>();\n const headers = new Map<string, Set<string | null>>();\n const internalGrants = new Map<string, Set<string | null>>();\n\n for (const adminConfig of adminConfigs) {\n for (const source of [adminConfig, adminConfig.force]) {\n for (const [name, value] of Object.entries(coerceObject(source?.env))) {\n env.add(nameValueIdentity(name, value));\n }\n const rules = migratedHostRules(source?.hostRules);\n for (const [identity, matchHosts] of headersByIdentity(rules)) {\n const hosts = headers.get(identity) ?? new Set<string | null>();\n for (const matchHost of matchHosts) {\n hosts.add(matchHost);\n }\n headers.set(identity, hosts);\n }\n for (const rule of rules) {\n if (!isUndefined(rule.allowInternal)) {\n const key = rule.allowInternal.toString();\n const hosts = internalGrants.get(key) ?? new Set<string | null>();\n hosts.add(rule.matchHost ?? null);\n internalGrants.set(key, hosts);\n }\n }\n }\n }\n\n return { env, headers, internalGrants };\n}\n\n/**\n * Return `resolved` without the security-sensitive (`env` and `hostRules[].headers`) values the self-hosted admin supplied themselves.\n *\n * `allowedEnv`/`allowedHeaders` exist to constrain what repository config, and the presets it extends, may inject; the self-hosted admin is who sets those allowlists, so their own values are not violations of them.\n *\n * Reporting them would abort the repository and file a \"Fix Renovate Configuration\" issue whose cause the repository's owners can neither see nor fix.\n */\nfunction withoutAdminSuppliedValues(\n resolved: RenovateConfig,\n admin: AdminSuppliedValues,\n): RenovateConfig {\n const result = { ...resolved };\n\n if (result.env) {\n result.env = Object.fromEntries(\n Object.entries(result.env).filter(\n ([name, value]) => !admin.env.has(nameValueIdentity(name, value)),\n ),\n );\n }\n\n // A header is the admin's own when its name and value match one the admin set for hosts that already cover this rule's hosts - the exact `matchHost` spelling must not matter, as migration and presets can re-spell (e.g. add a scheme) or narrow (e.g. a subpath) it\n if (result.hostRules) {\n result.hostRules = result.hostRules.map((rule) => {\n const filtered: HostRule = {\n ...rule,\n headers: Object.fromEntries(\n Object.entries(coerceObject(rule.headers)).filter(([name, value]) => {\n const adminHosts = admin.headers.get(\n nameValueIdentity(name, value),\n );\n if (!adminHosts) {\n // not a header the admin set - report it\n return true;\n }\n if (adminHosts.has(null)) {\n // the admin already sends it to every host\n return false;\n }\n // a host-less rule reaches every host, so only a host-less admin header (above) can exempt it\n return !(\n rule.matchHost &&\n [...adminHosts].some((adminHost) =>\n isWithinAdminHost(rule.matchHost!, adminHost),\n )\n );\n }),\n ),\n };\n\n // same principle for `allowInternal`: the admin's own value, for hosts their own rules already cover, is not a violation\n if (!isUndefined(filtered.allowInternal)) {\n const adminHosts = admin.internalGrants.get(\n filtered.allowInternal.toString(),\n );\n if (isCoveredByAdminHosts(adminHosts, filtered.matchHost)) {\n delete filtered.allowInternal;\n }\n }\n\n return filtered;\n });\n }\n\n // `mergeChildConfig` promotes `force` values into the config it returns, so the admin's own `force.env`/`force.hostRules[].headers` are applied - and exempted - the same way their top-level equivalents are\n if (result.force) {\n result.force = withoutAdminSuppliedValues(result.force, admin);\n }\n\n return result;\n}\n\n// Check for repository config\nexport async function mergeRenovateConfig(\n config: RepositoryWorkerConfig,\n branchName?: string,\n): Promise<RenovateConfig> {\n let returnConfig: RepositoryWorkerConfig = { ...config };\n let repoConfig: RepoFileConfig = {};\n if (getInheritedOrGlobal('requireConfig') !== 'ignored') {\n repoConfig = await detectRepoFileConfig(branchName);\n }\n if (!repoConfig.configFileParsed && config.mode === 'silent') {\n logger.debug(\n 'When mode=silent and repo has no config file, we use the onboarding config as repo config',\n );\n const configFileName = getDefaultConfigFileName();\n repoConfig = {\n configFileName,\n configFileParsed: await getOnboardingConfig(config),\n };\n }\n const configFileParsed = coerceObject(repoConfig?.configFileParsed);\n const resolvedRepoConfig = await resolveStaticRepoConfig(\n configFileParsed,\n process.env.RENOVATE_X_STATIC_REPO_CONFIG_FILE,\n );\n\n // Apply the repositories[] object-entry config between global config and\n // repository file config.\n // Must run after repository file config is loaded so its `ignorePresets` can\n // be included when resolving object-entry presets.\n const repoEntryConfig = returnConfig.repositoryEntryConfig;\n delete returnConfig.repositoryEntryConfig;\n\n // The presets the self-hosted admin's own config extends are their config too - a repository which merely inherits them must neither be blamed for what they contribute, nor have it filtered out from under it.\n // They are resolved separately because below they are resolved together with the repository's own presets, leaving no way to tell one from the other; a failure here is left to that resolution to report, as it is the one whose result is used.\n let adminPresetConfig: AllConfig = {};\n if (isNonEmptyArray(returnConfig.extends)) {\n try {\n ({ config: adminPresetConfig } = await presets.resolveConfigPresets(\n { extends: returnConfig.extends },\n config,\n config.ignorePresets,\n ));\n } catch (err) {\n logger.debug(\n { err },\n 'Error resolving the self-hosted config presets - continuing without their exemption',\n );\n }\n }\n\n // self-hosted configuration is always allowed\n // `force.env` is included because `mergeChildConfig` promotes `force` values to the top level as configs are merged\n const adminSuppliedEnv = {\n // presets the admin extends: as much theirs as anything they set inline, which is why they are listed first - the values they set themselves win\n ...coerceObject(adminPresetConfig.env),\n ...coerceObject(adminPresetConfig.force?.env),\n // `env` settings the self-hosted admin supplied (via `config.js`, etc), `env`, etc\n ...coerceObject(config.env),\n ...coerceObject(config.force?.env),\n // `repositories[]` entry for this repo - refreshed with the resolved values below, once its own presets, secrets and variables have been applied\n ...coerceObject(repoEntryConfig?.env),\n ...coerceObject(repoEntryConfig?.force?.env),\n };\n\n // every config the self-hosted admin supplied, in resolved form, for {@link adminSuppliedValues}\n const adminConfigs: RenovateConfig[] = [config, adminPresetConfig];\n\n if (isNonEmptyObject(repoEntryConfig)) {\n const repoEntry = repoEntryConfig as RenovateConfig;\n const toResolve: RenovateConfig = {\n ...repoEntry,\n extends: [\n ...coerceArray(returnConfig.extends),\n ...coerceArray(repoEntry.extends),\n ],\n ignorePresets: [\n ...coerceArray(returnConfig.ignorePresets),\n ...coerceArray(repoEntry.ignorePresets),\n ...coerceArray(resolvedRepoConfig.ignorePresets),\n ],\n };\n delete returnConfig.extends;\n\n let { config: resolvedRepoEntry } = await presets.resolveConfigPresets(\n toResolve,\n config,\n );\n\n // Migrate before validating so legacy option names contributed by the entry or its presets are migrated rather than reported as invalid options.\n const entryMigration = migrateConfigOrWarn(resolvedRepoEntry);\n if (entryMigration.isMigrated) {\n resolvedRepoEntry = entryMigration.migratedConfig;\n }\n\n // Migrate the entry's own config the same way, so its values compare like for like below: migration can rewrite them (e.g. a legacy `hostName` becoming a `matchHost`, or a bare `matchHost` gaining a scheme), and the resolved config only ever contains the migrated spellings\n const { migratedConfig: migratedEntry } = migrateConfigOrWarn(toResolve);\n // `resolveConfigPresets` removes both of these from its result\n delete migratedEntry.extends;\n delete migratedEntry.ignorePresets;\n\n // The entry, and every preset it extends, is the self-hosted admin's own config, so its `env`/`headers` are exempt from the allowlists the admin set - but the rest of the resolved result is still worth validating before any of it is applied (npmrc, hostRules, env).\n // When resolution and migration changed nothing, the presets contributed nothing and the entry itself was already validated as part of the admin's global config, so skip the (costly) validation walk entirely.\n adminConfigs.push(resolvedRepoEntry);\n if (!dequal(resolvedRepoEntry, migratedEntry)) {\n await validateResolvedConfig(\n withoutAdminSuppliedValues(\n resolvedRepoEntry,\n adminSuppliedValues(adminConfigs),\n ),\n repositoriesEntrySource,\n config.configValidationError === true,\n repositoriesEntryValidationError,\n );\n }\n\n applyNpmrc(resolvedRepoEntry, 'resolvedRepoEntry');\n\n const resolvedRepoEntryWithSecrets = applySecretsAndVariablesToConfig({\n config: resolvedRepoEntry,\n // like the repository config below, the entry can carry its own `secrets`/`variables` - `validateConfigSecretsAndVariables` validates them at startup\n secrets: mergeChildConfig(\n coerceObject(config.secrets),\n coerceObject(resolvedRepoEntry.secrets),\n ),\n variables: mergeChildConfig(\n coerceObject(config.variables),\n coerceObject(resolvedRepoEntry.variables),\n ),\n });\n\n // Refresh the admin-supplied snapshot from the resolved entry: it also carries whatever the presets the entry extends contributed, and its `env` values may contain `{{ secrets.* }}`/`{{ variables.* }}` templates only interpolated here - e.g. when the secrets are defined on the entry itself rather than globally.\n // Interpolation is recursive, so the interpolated `force.env` values stay nested under `force`.\n Object.assign(\n adminSuppliedEnv,\n coerceObject(resolvedRepoEntryWithSecrets.env),\n coerceObject(resolvedRepoEntryWithSecrets.force?.env),\n );\n\n // the `repositories[]` entry is the self-hosted admin's own config - as its `env` is already treated as admin-supplied, its rules are `trusted` too, so that an admin can still override a header they set globally for just this repository\n applyHostRules(resolvedRepoEntryWithSecrets, { trusted: true });\n returnConfig = mergeChildConfig(returnConfig, resolvedRepoEntryWithSecrets);\n }\n\n if (isNonEmptyArray(returnConfig.extends)) {\n resolvedRepoConfig.extends = [\n ...coerceArray(returnConfig.extends),\n ...coerceArray(resolvedRepoConfig.extends),\n ];\n delete returnConfig.extends;\n }\n checkForRepoConfigError(repoConfig);\n const migratedConfig = await migrateAndValidate(config, resolvedRepoConfig);\n if (migratedConfig.errors?.length) {\n throwConfigValidationError(\n repoConfig.configFileName,\n migratedConfig.errors,\n );\n }\n // v8 ignore else -- migration always leaves a warnings array behind\n if (migratedConfig.warnings) {\n returnConfig.warnings = [\n ...coerceArray(returnConfig.warnings),\n ...migratedConfig.warnings,\n ];\n }\n delete migratedConfig.errors;\n delete migratedConfig.warnings;\n // TODO #22198\n const repository = config.repository!;\n // Decrypt before resolving in case we need npm authentication for any presets\n const decryptedConfig = await decryptConfig(migratedConfig, repository);\n applyNpmrc(decryptedConfig, 'decrypted');\n\n // NOTE that this should not be used with any other configuration (`resolvedConfig`, etc) below, as they will include addditionally merged configuration\n // Decrypted secrets are sanitised, so should be safe to log\n await logShallowConfig(decryptedConfig, config);\n\n // Decrypt after resolving in case the preset contains npm authentication instead\n const { config: configToDecrypt } = await presets.resolveConfigPresets(\n decryptedConfig,\n config,\n config.ignorePresets,\n );\n let resolvedConfig = await decryptConfig(configToDecrypt, repository);\n logger.trace({ config: resolvedConfig }, 'resolved config');\n const migrationResult = migrateConfig(resolvedConfig);\n if (migrationResult.isMigrated) {\n logger.debug('Resolved config needs migrating');\n logger.trace({ config: resolvedConfig }, 'resolved config after migrating');\n resolvedConfig = migrationResult.migratedConfig;\n }\n\n // Validate the fully-resolved repository config, enforcing validation is applied against all stages of the preset, and providing defence-in-depth for any sensitive config options\n // note that we do not need to re-run `migrateAndValidate` if we're already at the same configuration that we've previously resolved, decrypted and migrated, so we can avoid a costly re-validation\n if (!dequal(resolvedConfig, migratedConfig)) {\n await validateResolvedConfig(\n // the admin's own `extends` are resolved into this config alongside the repository's, so exempt what they contributed: the repository can neither see nor fix it\n withoutAdminSuppliedValues(\n resolvedConfig,\n adminSuppliedValues(adminConfigs),\n ),\n // a repository that is not yet onboarded has no config file to blame; 'config' mirrors other unattributable validation errors (e.g. `decryptConfig`)\n repoConfig.configFileName ?? 'config',\n config.configValidationError === true,\n );\n }\n if (isString(resolvedConfig.npmrc)) {\n logger.debug(\n 'Ignoring any .npmrc files in repository due to configured npmrc',\n );\n }\n applyNpmrc(resolvedConfig, 'resolved');\n resolvedConfig = applySecretsAndVariablesToConfig({\n config: resolvedConfig,\n secrets: mergeChildConfig(\n coerceObject(config.secrets),\n coerceObject(resolvedConfig.secrets),\n ),\n variables: mergeChildConfig(\n coerceObject(config.variables),\n coerceObject(resolvedConfig.variables),\n ),\n });\n\n applyHostRules(resolvedConfig);\n returnConfig = mergeChildConfig(returnConfig, resolvedConfig);\n ({ config: returnConfig } = await presets.resolveConfigPresets(\n returnConfig,\n config,\n ));\n returnConfig.renovateJsonPresent = true;\n // istanbul ignore if\n if (returnConfig.ignorePaths?.length) {\n logger.debug(\n { ignorePaths: returnConfig.ignorePaths },\n `Found repo ignorePaths`,\n );\n }\n\n setUserEnv(filterAllowedEnv(returnConfig.env, adminSuppliedEnv));\n delete returnConfig.env;\n\n return returnConfig;\n}\n\nexport function applyNpmrc(\n config: RenovateConfig,\n configType?: 'resolved' | 'resolvedRepoEntry' | 'decrypted',\n): void {\n setNpmTokenInNpmrc(config);\n if (!isString(config.npmrc)) {\n return;\n }\n logger.debug(\n `Setting npmrc from ${configType ? `${configType} ` : ''}config`,\n );\n npmApi.setNpmrc(config.npmrc);\n}\n\nexport function applyHostRules(\n config: RenovateConfig,\n options?: hostRules.AddHostRuleOptions,\n): void {\n if (!config.hostRules) {\n return;\n }\n\n logger.debug('Setting hostRules from config');\n // `hostRules.add` enforces `allowedHeaders` on every untrusted rule it registers - a `trusted` rule (see `options`) is exempt\n for (const rule of config.hostRules) {\n try {\n hostRules.add(rule, options);\n } catch (err) {\n logger.warn({ err, config: rule }, 'Error setting hostRule from config');\n }\n }\n // host rules can change concurrency\n queue.clear();\n throttle.clear();\n delete config.hostRules;\n}\n\n/** needed when using portal secrets for npmToken */\nexport function setNpmTokenInNpmrc(config: RenovateConfig): void {\n if (!isString(config.npmToken)) {\n return;\n }\n\n const token = config.npmToken;\n logger.debug({ npmToken: maskToken(token) }, 'Migrating npmToken to npmrc');\n\n if (!isString(config.npmrc)) {\n logger.debug('Adding npmrc to config');\n config.npmrc = `//registry.npmjs.org/:_authToken=${token}\\n`;\n delete config.npmToken;\n return;\n }\n\n if (config.npmrc.includes(`\\${NPM_TOKEN}`)) {\n logger.debug(`Replacing \\${NPM_TOKEN} with npmToken`);\n config.npmrc = config.npmrc.replace(regEx(/\\${NPM_TOKEN}/g), token);\n } else {\n logger.debug('Appending _authToken= to end of existing npmrc');\n config.npmrc = config.npmrc.replace(\n regEx(/\\n?$/),\n `\\n_authToken=${token}\\n`,\n );\n }\n\n delete config.npmToken;\n}\n\nexport async function resolveStaticRepoConfig(\n config: AllConfig,\n filename: string | undefined,\n): Promise<AllConfig> {\n if (!isNonEmptyString(filename)) {\n return config;\n }\n\n let staticRepoConfig: AllConfig;\n\n try {\n staticRepoConfig = await tryReadStaticRepoFileConfig(filename);\n } catch (err) {\n logger.fatal({ err }, 'Failed to load static repository config file');\n process.exit(1);\n }\n\n if (!isNonEmptyObject(staticRepoConfig)) {\n return config;\n }\n\n return mergeStaticConfig(config, staticRepoConfig);\n}\n\nexport async function tryReadStaticRepoFileConfig(\n staticRepoConfigFile: string,\n): Promise<AllConfig> {\n logger.debug(`Reading static repo config file from ${staticRepoConfigFile}`);\n\n let staticRepoConfigRaw: string;\n try {\n staticRepoConfigRaw = await readSystemFile(staticRepoConfigFile, 'utf8');\n } catch (err) {\n throw new Error(\n `Failed to read static repo config file: \"${staticRepoConfigFile}\"`,\n { cause: err },\n );\n }\n\n const staticRepoConfig = parseJson(\n staticRepoConfigRaw,\n staticRepoConfigFile,\n ) as AllConfig;\n\n // validate and log issues here to preserve context, caller handles migration and full validation.\n const { errors, warnings } = await configValidation.validateConfig(\n 'repo',\n // `validateConfig` expects massaged input\n massageConfig(staticRepoConfig),\n );\n\n if (isNonEmptyArray(errors) || isNonEmptyArray(warnings)) {\n logger.info(\n { errors, warnings },\n 'Static repo config validation issues detected',\n );\n } else {\n logger.debug(\n { staticRepoConfig },\n 'Static repository config file successfully parsed and validated',\n );\n }\n\n return staticRepoConfig;\n}\n\nexport function mergeStaticConfig(\n config: AllConfig,\n staticRepoConfig: AllConfig,\n): AllConfig {\n // merge extends\n if (isNonEmptyArray(staticRepoConfig.extends)) {\n config.extends = [\n ...staticRepoConfig.extends,\n ...coerceArray(config.extends),\n ];\n delete staticRepoConfig.extends;\n }\n\n // renovate repo config overrides RENOVATE_STATIC_REPO_CONFIG[_FILE]\n return mergeChildConfig(staticRepoConfig, config);\n}\n\n/**\n * Resolve everything but internal Renovate presets and log it out.\n *\n* This allows users to understand the fully resolved configuration, including any `github>`, `local>`, etc presets, but excluding anything that's internal to Renovate (which can be verbose and/or less relevant), and provides useful output for debugging purposes.\n\n* This is also known as the \"shallow\" config.\n\n* Due to caching, this doesn't add any additional requests.\n */\nasync function logShallowConfig(\n _decryptedConfig: RenovateConfig,\n _config: RepositoryWorkerConfig,\n): Promise<void> {\n // make sure we clone the existing config, so we don't modify the existing settings when resolving this in a shallow fashion\n const decryptedConfig = clone(_decryptedConfig);\n const config = clone(_config);\n\n const { config: resolvedConfig, visitedPresets } =\n await presets.resolveConfigPresets(\n clone(decryptedConfig),\n clone(config),\n config.ignorePresets,\n [],\n false,\n );\n logger.debug(\n {\n renovateVersion: pkg.version,\n config: resolvedConfig,\n visitedPresets,\n },\n 'Resolved shallow config, without merging internal presets',\n );\n}\n"],"mappings":"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"}
|
|
@@ -65,7 +65,8 @@ async function isOnboarded(config) {
|
|
|
65
65
|
logger.debug("Checking cached config file name");
|
|
66
66
|
try {
|
|
67
67
|
const configFileContent = await platform.getJsonFile(cache.configFileName);
|
|
68
|
-
|
|
68
|
+
const hasRenovateConfig = cache.configFileName !== "package.json" || configFileContent?.renovate;
|
|
69
|
+
if (configFileContent && hasRenovateConfig) {
|
|
69
70
|
logger.debug("Existing config file confirmed");
|
|
70
71
|
logger.debug({
|
|
71
72
|
fileName: cache.configFileName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","names":[],"sources":["../../../../../lib/workers/repository/onboarding/branch/check.ts"],"sourcesContent":["import { isNonEmptyObject } from '@sindresorhus/is';\nimport { getConfigFileNames } from '../../../../config/app-strings.ts';\nimport type { RenovateConfig } from '../../../../config/types.ts';\nimport {\n REPOSITORY_CLOSED_ONBOARDING,\n REPOSITORY_NO_CONFIG,\n} from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { ensureComment } from '../../../../modules/platform/comment.ts';\nimport type { Pr } from '../../../../modules/platform/index.ts';\nimport { platform } from '../../../../modules/platform/index.ts';\nimport { scm } from '../../../../modules/platform/scm.ts';\nimport { getCache } from '../../../../util/cache/repository/index.ts';\nimport { getInheritedOrGlobal } from '../../../../util/common.ts';\nimport { getElapsedDays } from '../../../../util/date.ts';\nimport { readLocalFile } from '../../../../util/fs/index.ts';\nimport { getBranchCommit } from '../../../../util/git/index.ts';\nimport { getSemanticCommitPrTitle } from '../common.ts';\n\nasync function findFile(fileName: string): Promise<boolean> {\n logger.debug(`findFile(${fileName})`);\n const fileList = await scm.getFileList();\n return fileList.includes(fileName);\n}\n\nasync function configFileExists(): Promise<boolean> {\n for (const fileName of getConfigFileNames()) {\n if (fileName !== 'package.json' && (await findFile(fileName))) {\n logger.debug(`Config file exists, fileName: ${fileName}`);\n return true;\n }\n }\n return false;\n}\n\nasync function packageJsonConfigExists(): Promise<boolean> {\n try {\n // TODO #22198\n const pJson = JSON.parse((await readLocalFile('package.json', 'utf8'))!);\n if (pJson.renovate) {\n return true;\n }\n } catch {\n // Do nothing\n }\n return false;\n}\n\nasync function closedPrExists(config: RenovateConfig): Promise<Pr | null> {\n return (\n (await platform.findPr({\n branchName: getInheritedOrGlobal('onboardingBranch')!,\n prTitle: getInheritedOrGlobal('onboardingPrTitle'),\n state: '!open',\n targetBranch: config.baseBranch,\n })) ??\n (await platform.findPr({\n branchName: getInheritedOrGlobal('onboardingBranch')!,\n prTitle: getSemanticCommitPrTitle(config),\n state: '!open',\n targetBranch: config.baseBranch,\n }))\n );\n}\n\nexport async function isOnboarded(config: RenovateConfig): Promise<boolean> {\n logger.debug('isOnboarded()');\n const title = `Action required: Add a Renovate config`;\n\n // Repo is onboarded if in silent mode\n if (config.mode === 'silent') {\n logger.debug('Silent mode enabled so repo is considered onboarded');\n return true;\n }\n\n // Repo is onboarded if global config is bypassing onboarding and does not require a\n // configuration file.\n // The repo is considered \"not onboarded\" if:\n // - An onboarding cache is present, and\n // - The current default branch SHA matches the default SHA found in the cache\n // Also if there is a closed pr skip using cache as it is outdated\n if (\n getInheritedOrGlobal('requireConfig') === 'optional' &&\n getInheritedOrGlobal('onboarding') === false\n ) {\n // Return early and avoid checking for config files\n return true;\n }\n if (getInheritedOrGlobal('requireConfig') === 'ignored') {\n logger.debug('Config file will be ignored');\n return true;\n }\n\n const closedOnboardingPr = await closedPrExists(config);\n const cache = getCache();\n const onboardingBranchCache = cache?.onboardingBranchCache;\n // if onboarding cache is present and base branch has not been updated; branch is not onboarded\n // if closed pr exists then presence of onboarding cache doesn't matter as we need to skip onboarding\n if (\n getInheritedOrGlobal('onboarding') &&\n !closedOnboardingPr &&\n isNonEmptyObject(onboardingBranchCache) &&\n onboardingBranchCache.defaultBranchSha ===\n getBranchCommit(config.defaultBranch!)\n ) {\n logger.debug('Onboarding cache is valid. Repo is not onboarded');\n return false;\n }\n\n // when Renovate is running in fork mode ... do not fetch file using api call instead use the git.fileList so we get sync first and get the latest config\n // prevents https://github.com/renovatebot/renovate/discussions/37328\n if (cache.configFileName && !config.forkToken) {\n logger.debug('Checking cached config file name');\n try {\n const configFileContent = await platform.getJsonFile(\n cache.configFileName,\n );\n if (\n configFileContent &&\n (cache.configFileName !== 'package.json' || configFileContent.renovate)\n ) {\n logger.debug('Existing config file confirmed');\n logger.debug(\n { fileName: cache.configFileName, config: configFileContent },\n 'Repository config',\n );\n return true;\n }\n } catch {\n // probably file doesn't exist\n }\n logger.debug('Existing config file no longer exists');\n delete cache.configFileName;\n }\n if (await configFileExists()) {\n await platform.ensureIssueClosing(title);\n return true;\n }\n logger.debug('config file not found');\n if (await packageJsonConfigExists()) {\n logger.debug('package.json contains config');\n await platform.ensureIssueClosing(title);\n return true;\n }\n\n // If onboarding has been disabled and config files are required then the\n // repository has not been onboarded yet\n if (\n getInheritedOrGlobal('requireConfig') === 'required' &&\n getInheritedOrGlobal('onboarding') === false\n ) {\n throw new Error(REPOSITORY_NO_CONFIG);\n }\n\n if (!closedOnboardingPr) {\n logger.debug('Found no closed onboarding PR');\n return false;\n }\n logger.debug('Found closed onboarding PR');\n if (getInheritedOrGlobal('requireConfig') === 'optional') {\n logger.debug('Config not mandatory so repo is considered onboarded');\n return true;\n }\n logger.debug('Repo is not onboarded and no merged PRs exist');\n if (!config.suppressNotifications!.includes('onboardingClose')) {\n const ageOfOnboardingPr = getElapsedDays(\n closedOnboardingPr.createdAt!,\n false,\n );\n const onboardingAutoCloseAge = getInheritedOrGlobal(\n 'onboardingAutoCloseAge',\n );\n if (onboardingAutoCloseAge) {\n logger.debug(\n {\n onboardingAutoCloseAge,\n createdAt: closedOnboardingPr.createdAt!,\n ageOfOnboardingPr,\n },\n `Determining that the closed onboarding PR was created at \\`${closedOnboardingPr.createdAt!}\\` was created ${ageOfOnboardingPr.toFixed(2)} days ago`,\n );\n }\n // if we have onboardingAutoCloseAge, and it hasn't yet passed onboardingAutoCloseAge, add a comment\n // if it /has/ passed, we'll comment this appropriately in `ensureOnboardingPr`, so there doesn't need to be a comment here\n if (\n !onboardingAutoCloseAge ||\n ageOfOnboardingPr <= onboardingAutoCloseAge\n ) {\n // ensure PR comment\n await ensureComment({\n number: closedOnboardingPr.number,\n topic: `Renovate is disabled`,\n content: `Renovate is disabled because there is no Renovate configuration file. To enable Renovate, you can either (a) change this PR's title to get a new onboarding PR, and merge the new onboarding PR, or (b) create a Renovate config file, and commit that file to your base branch.`,\n });\n }\n }\n throw new Error(REPOSITORY_CLOSED_ONBOARDING);\n}\n\nexport async function getOnboardingPr(\n config: RenovateConfig,\n): Promise<Pr | null> {\n return await platform.getBranchPr(\n getInheritedOrGlobal('onboardingBranch')!,\n config.baseBranch,\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"check.js","names":[],"sources":["../../../../../lib/workers/repository/onboarding/branch/check.ts"],"sourcesContent":["import { isNonEmptyObject } from '@sindresorhus/is';\nimport { getConfigFileNames } from '../../../../config/app-strings.ts';\nimport type { RenovateConfig } from '../../../../config/types.ts';\nimport {\n REPOSITORY_CLOSED_ONBOARDING,\n REPOSITORY_NO_CONFIG,\n} from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { ensureComment } from '../../../../modules/platform/comment.ts';\nimport type { Pr } from '../../../../modules/platform/index.ts';\nimport { platform } from '../../../../modules/platform/index.ts';\nimport { scm } from '../../../../modules/platform/scm.ts';\nimport { getCache } from '../../../../util/cache/repository/index.ts';\nimport { getInheritedOrGlobal } from '../../../../util/common.ts';\nimport { getElapsedDays } from '../../../../util/date.ts';\nimport { readLocalFile } from '../../../../util/fs/index.ts';\nimport { getBranchCommit } from '../../../../util/git/index.ts';\nimport { getSemanticCommitPrTitle } from '../common.ts';\n\nasync function findFile(fileName: string): Promise<boolean> {\n logger.debug(`findFile(${fileName})`);\n const fileList = await scm.getFileList();\n return fileList.includes(fileName);\n}\n\nasync function configFileExists(): Promise<boolean> {\n for (const fileName of getConfigFileNames()) {\n if (fileName !== 'package.json' && (await findFile(fileName))) {\n logger.debug(`Config file exists, fileName: ${fileName}`);\n return true;\n }\n }\n return false;\n}\n\nasync function packageJsonConfigExists(): Promise<boolean> {\n try {\n // TODO #22198\n const pJson = JSON.parse((await readLocalFile('package.json', 'utf8'))!);\n if (pJson.renovate) {\n return true;\n }\n } catch {\n // Do nothing\n }\n return false;\n}\n\nasync function closedPrExists(config: RenovateConfig): Promise<Pr | null> {\n return (\n (await platform.findPr({\n branchName: getInheritedOrGlobal('onboardingBranch')!,\n prTitle: getInheritedOrGlobal('onboardingPrTitle'),\n state: '!open',\n targetBranch: config.baseBranch,\n })) ??\n (await platform.findPr({\n branchName: getInheritedOrGlobal('onboardingBranch')!,\n prTitle: getSemanticCommitPrTitle(config),\n state: '!open',\n targetBranch: config.baseBranch,\n }))\n );\n}\n\nexport async function isOnboarded(config: RenovateConfig): Promise<boolean> {\n logger.debug('isOnboarded()');\n const title = `Action required: Add a Renovate config`;\n\n // Repo is onboarded if in silent mode\n if (config.mode === 'silent') {\n logger.debug('Silent mode enabled so repo is considered onboarded');\n return true;\n }\n\n // Repo is onboarded if global config is bypassing onboarding and does not require a\n // configuration file.\n // The repo is considered \"not onboarded\" if:\n // - An onboarding cache is present, and\n // - The current default branch SHA matches the default SHA found in the cache\n // Also if there is a closed pr skip using cache as it is outdated\n if (\n getInheritedOrGlobal('requireConfig') === 'optional' &&\n getInheritedOrGlobal('onboarding') === false\n ) {\n // Return early and avoid checking for config files\n return true;\n }\n if (getInheritedOrGlobal('requireConfig') === 'ignored') {\n logger.debug('Config file will be ignored');\n return true;\n }\n\n const closedOnboardingPr = await closedPrExists(config);\n const cache = getCache();\n const onboardingBranchCache = cache?.onboardingBranchCache;\n // if onboarding cache is present and base branch has not been updated; branch is not onboarded\n // if closed pr exists then presence of onboarding cache doesn't matter as we need to skip onboarding\n if (\n getInheritedOrGlobal('onboarding') &&\n !closedOnboardingPr &&\n isNonEmptyObject(onboardingBranchCache) &&\n onboardingBranchCache.defaultBranchSha ===\n getBranchCommit(config.defaultBranch!)\n ) {\n logger.debug('Onboarding cache is valid. Repo is not onboarded');\n return false;\n }\n\n // when Renovate is running in fork mode ... do not fetch file using api call instead use the git.fileList so we get sync first and get the latest config\n // prevents https://github.com/renovatebot/renovate/discussions/37328\n if (cache.configFileName && !config.forkToken) {\n logger.debug('Checking cached config file name');\n try {\n const configFileContent = await platform.getJsonFile(\n cache.configFileName,\n );\n const hasRenovateConfig =\n cache.configFileName !== 'package.json' || configFileContent?.renovate;\n if (configFileContent && hasRenovateConfig) {\n logger.debug('Existing config file confirmed');\n logger.debug(\n { fileName: cache.configFileName, config: configFileContent },\n 'Repository config',\n );\n return true;\n }\n } catch {\n // probably file doesn't exist\n }\n logger.debug('Existing config file no longer exists');\n delete cache.configFileName;\n }\n if (await configFileExists()) {\n await platform.ensureIssueClosing(title);\n return true;\n }\n logger.debug('config file not found');\n if (await packageJsonConfigExists()) {\n logger.debug('package.json contains config');\n await platform.ensureIssueClosing(title);\n return true;\n }\n\n // If onboarding has been disabled and config files are required then the\n // repository has not been onboarded yet\n if (\n getInheritedOrGlobal('requireConfig') === 'required' &&\n getInheritedOrGlobal('onboarding') === false\n ) {\n throw new Error(REPOSITORY_NO_CONFIG);\n }\n\n if (!closedOnboardingPr) {\n logger.debug('Found no closed onboarding PR');\n return false;\n }\n logger.debug('Found closed onboarding PR');\n if (getInheritedOrGlobal('requireConfig') === 'optional') {\n logger.debug('Config not mandatory so repo is considered onboarded');\n return true;\n }\n logger.debug('Repo is not onboarded and no merged PRs exist');\n if (!config.suppressNotifications!.includes('onboardingClose')) {\n const ageOfOnboardingPr = getElapsedDays(\n closedOnboardingPr.createdAt!,\n false,\n );\n const onboardingAutoCloseAge = getInheritedOrGlobal(\n 'onboardingAutoCloseAge',\n );\n if (onboardingAutoCloseAge) {\n logger.debug(\n {\n onboardingAutoCloseAge,\n createdAt: closedOnboardingPr.createdAt!,\n ageOfOnboardingPr,\n },\n `Determining that the closed onboarding PR was created at \\`${closedOnboardingPr.createdAt!}\\` was created ${ageOfOnboardingPr.toFixed(2)} days ago`,\n );\n }\n // if we have onboardingAutoCloseAge, and it hasn't yet passed onboardingAutoCloseAge, add a comment\n // if it /has/ passed, we'll comment this appropriately in `ensureOnboardingPr`, so there doesn't need to be a comment here\n if (\n !onboardingAutoCloseAge ||\n ageOfOnboardingPr <= onboardingAutoCloseAge\n ) {\n // ensure PR comment\n await ensureComment({\n number: closedOnboardingPr.number,\n topic: `Renovate is disabled`,\n content: `Renovate is disabled because there is no Renovate configuration file. To enable Renovate, you can either (a) change this PR's title to get a new onboarding PR, and merge the new onboarding PR, or (b) create a Renovate config file, and commit that file to your base branch.`,\n });\n }\n }\n throw new Error(REPOSITORY_CLOSED_ONBOARDING);\n}\n\nexport async function getOnboardingPr(\n config: RenovateConfig,\n): Promise<Pr | null> {\n return await platform.getBranchPr(\n getInheritedOrGlobal('onboardingBranch')!,\n config.baseBranch,\n );\n}\n"],"mappings":"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"}
|
|
@@ -30,7 +30,8 @@ function resolveConcurrentLimit(config) {
|
|
|
30
30
|
};
|
|
31
31
|
const prConcurrentLimit = calcLimit([configAsUpgrade], "prConcurrentLimit");
|
|
32
32
|
const branchConcurrentLimit = calcLimit([configAsUpgrade], "branchConcurrentLimit");
|
|
33
|
-
|
|
33
|
+
const isBelowPrLimit = prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit;
|
|
34
|
+
if (typeof config.branchConcurrentLimit === "number" && branchConcurrentLimit > 0 && isBelowPrLimit) return {
|
|
34
35
|
limit: branchConcurrentLimit,
|
|
35
36
|
key: "branchConcurrentLimit"
|
|
36
37
|
};
|
|
@@ -55,7 +56,8 @@ function resolveVulnerabilityConcurrentLimit(config) {
|
|
|
55
56
|
};
|
|
56
57
|
const prConcurrentLimit = calcLimit([configAsUpgrade], "prConcurrentLimit");
|
|
57
58
|
const branchConcurrentLimit = calcLimit([configAsUpgrade], "branchConcurrentLimit");
|
|
58
|
-
|
|
59
|
+
const isBelowPrLimit = prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit;
|
|
60
|
+
if (typeof vulnerabilityAlerts?.branchConcurrentLimit === "number" && branchConcurrentLimit > 0 && isBelowPrLimit) return {
|
|
59
61
|
limit: branchConcurrentLimit,
|
|
60
62
|
key: "branchConcurrentLimit"
|
|
61
63
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-list.js","names":[],"sources":["../../../../../lib/workers/repository/onboarding/pr/pr-list.ts"],"sourcesContent":["import { getDefault } from '../../../../config/defaults.ts';\nimport { GlobalConfig } from '../../../../config/global.ts';\nimport { getOptions } from '../../../../config/options/index.ts';\nimport {\n type RenovateConfig,\n type UpdateType,\n UpdateTypesOptions,\n} from '../../../../config/types.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { emojify } from '../../../../util/emoji.ts';\nimport { coerceNumber } from '../../../../util/number.ts';\nimport { regEx } from '../../../../util/regex.ts';\nimport { calcLimit } from '../../../global/limits.ts';\nimport type { BranchConfig, BranchUpgradeConfig } from '../../../types.ts';\n\n/**\n * The different categories of dependency updates to output, when providing the summary view.\n *\n * - `security`: if the upgrade is driven by a vulnerability alert\n * - `${updateType}`: if it's set. I.e. `major`\n * - `lockfileUpdate` when `isLockfileUpdate` is true, without an `updateType`\n * - `other`: otherwise\n */\ntype SummaryCategory = UpdateType | 'security' | 'other';\n\n/** Priority order when rendering the `SummaryCategory`s in the summary view.\n *\n * NOTE that this is not exhaustive - this is only the priority order for rendering, and other categories, such as `other` are placed after.\n */\nconst SUMMARY_CATEGORY_PRIORITY_ORDER: readonly SummaryCategory[] = [\n 'security',\n ...UpdateTypesOptions,\n // ... anything else\n];\n\ninterface ConcurrentLimit {\n limit: number;\n key: 'prConcurrentLimit' | 'branchConcurrentLimit';\n}\n\n/**\n * Resolves the concurrent limit that governs how many of the expected Pull Requests can be open at once,\n * reusing the same `calcLimit()` used to enforce these limits (see `lib/workers/global/limits.ts`).\n *\n * `branchConcurrentLimit` only takes priority when it's been explicitly configured (it's `null` by default,\n * in which case `calcLimit()` silently inherits the value of `prConcurrentLimit`) and is actually more\n * restrictive - otherwise we'd misattribute the limit to a setting the user never touched.\n */\nfunction resolveConcurrentLimit(config: RenovateConfig): ConcurrentLimit {\n const configAsUpgrade: BranchUpgradeConfig = {\n branchName: '',\n manager: '',\n prConcurrentLimit: config.prConcurrentLimit,\n branchConcurrentLimit: config.branchConcurrentLimit,\n };\n const prConcurrentLimit = calcLimit([configAsUpgrade], 'prConcurrentLimit');\n const branchConcurrentLimit = calcLimit(\n [configAsUpgrade],\n 'branchConcurrentLimit',\n );\n\n if (\n typeof config.branchConcurrentLimit === 'number' &&\n branchConcurrentLimit > 0 &&\n (prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit)\n ) {\n return {\n limit: branchConcurrentLimit,\n key: 'branchConcurrentLimit',\n };\n }\n\n return { limit: prConcurrentLimit, key: 'prConcurrentLimit' };\n}\n\n/**\n * Vulnerability alert fixes get their own concurrent-limit budget via `vulnerabilityAlerts.prConcurrentLimit`/ `vulnerabilityAlerts.branchConcurrentLimit`, separate from repository-wide/dependency-specific rules.\n * Falls back to the `vulnerabilityAlerts` option's own schema default (currently `0`, i.e. no limit) when\n * unset, via `getDefault()`, rather than duplicating that value here.\n */\nfunction resolveVulnerabilityConcurrentLimit(\n config: RenovateConfig,\n): ConcurrentLimit {\n // `vulnerabilityAlerts` is typed as `RenovateSharedConfig`, which doesn't declare `prConcurrentLimit`/\n // `branchConcurrentLimit`, even though both are valid nested options (see docs for `vulnerabilityAlerts`).\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion\n const vulnerabilityAlerts = config.vulnerabilityAlerts as\n RenovateConfig | undefined;\n const vulnerabilityAlertsDefault = getDefault(\n getOptions().find((option) => option.name === 'vulnerabilityAlerts')!,\n ) as RenovateConfig;\n const configAsUpgrade: BranchUpgradeConfig = {\n branchName: '',\n manager: '',\n prConcurrentLimit:\n vulnerabilityAlerts?.prConcurrentLimit ??\n vulnerabilityAlertsDefault.prConcurrentLimit,\n // `undefined` and `null` are handled identically by `calcLimit()` (both inherit `prConcurrentLimit`),\n // so there's no default value to duplicate here - unlike `prConcurrentLimit` above.\n branchConcurrentLimit: vulnerabilityAlerts?.branchConcurrentLimit,\n };\n const prConcurrentLimit = calcLimit([configAsUpgrade], 'prConcurrentLimit');\n const branchConcurrentLimit = calcLimit(\n [configAsUpgrade],\n 'branchConcurrentLimit',\n );\n\n if (\n typeof vulnerabilityAlerts?.branchConcurrentLimit === 'number' &&\n branchConcurrentLimit > 0 &&\n (prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit)\n ) {\n return {\n limit: branchConcurrentLimit,\n key: 'branchConcurrentLimit',\n };\n }\n\n return { limit: prConcurrentLimit, key: 'prConcurrentLimit' };\n}\n\nexport function getExpectedPrList(\n config: RenovateConfig,\n branches: BranchConfig[],\n): string {\n logger.debug('getExpectedPrList()');\n logger.trace({ config });\n let prDesc = `\\n### What to Expect\\n\\n`;\n if (!branches.length) {\n return `${prDesc}It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.\\n`;\n }\n // Vulnerability alert branches bypass the repository-wide rate/concurrency limits, so they shouldn't\n // count towards them - they get their own budget, see `resolveVulnerabilityConcurrentLimit()`.\n const securityBranchCount = branches.filter(\n (b) => b.isVulnerabilityAlert,\n ).length;\n const throttledBranchCount = branches.length - securityBranchCount;\n\n const { limit: concurrentLimit, key: concurrentLimitKey } =\n resolveConcurrentLimit(config);\n if (concurrentLimit > 0 && concurrentLimit < throttledBranchCount) {\n const securityNote =\n securityBranchCount > 0\n ? `, plus ${securityBranchCount} security update Pull Request${securityBranchCount > 1 ? 's' : ''} which ${securityBranchCount > 1 ? 'are' : 'is'} not subject to this limit`\n : '';\n prDesc += `With your current configuration, Renovate will create ${concurrentLimit} Pull Request${concurrentLimit > 1 ? 's' : ''}, up to a maximum of ${branches.length} over time (see [docs for \\`${concurrentLimitKey}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#${concurrentLimitKey.toLowerCase()}))${securityNote}:\\n\\n`;\n } else {\n prDesc += `With your current configuration, Renovate will create ${branches.length} Pull Request`;\n prDesc += branches.length > 1 ? `s:\\n\\n` : `:\\n\\n`;\n }\n prDesc += getSecurityConcurrentLimitNote(\n securityBranchCount,\n concurrentLimit,\n resolveVulnerabilityConcurrentLimit(config),\n );\n\n for (const branch of branches) {\n const prTitleRe = regEx(/@(?<scope>[a-z]+\\/[a-z]+)/);\n // TODO #22198\n prDesc += `<details>\\n<summary>${branch.prTitle!.replace(\n prTitleRe,\n '@​$<scope>',\n )}</summary>\\n\\n`;\n if (branch.schedule?.length) {\n prDesc += ` - Schedule: ${JSON.stringify(branch.schedule)}\\n`;\n }\n prDesc += ` - Branch name: \\`${branch.branchName}\\`\\n`;\n prDesc += branch.baseBranch\n ? ` - Merge into: \\`${branch.baseBranch}\\`\\n`\n : '';\n const seen: string[] = [];\n for (const upgrade of branch.upgrades) {\n let text = '';\n if (upgrade.updateType === 'lockFileMaintenance') {\n text += ' - Regenerate lock files to use latest dependency versions';\n } else {\n if (upgrade.updateType === 'pin') {\n text += ' - Pin ';\n } else {\n text += ' - Upgrade ';\n }\n if (upgrade.sourceUrl) {\n // TODO: types (#22198)\n text += `[${upgrade.depName!}](${upgrade.sourceUrl})`;\n } else {\n text += upgrade.depName!.replace(prTitleRe, '@​$1');\n }\n // TODO: types (#22198)\n text += upgrade.isLockfileUpdate\n ? ` to \\`${upgrade.newVersion!}\\``\n : ` to \\`${upgrade.newDigest ?? upgrade.newValue!}\\``;\n text += '\\n';\n }\n if (!seen.includes(text)) {\n prDesc += text;\n seen.push(text);\n }\n }\n prDesc += '\\n\\n';\n prDesc += '</details>\\n\\n';\n }\n const prHourlyLimit = coerceNumber(config.prHourlyLimit);\n const commitHourlyLimit = coerceNumber(config.commitHourlyLimit);\n const securityBypassNote =\n securityBranchCount > 0\n ? ` Security update Pull Request${securityBranchCount > 1 ? 's are' : ' is'} not subject to this limit and will be created straight away.`\n : '';\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < throttledBranchCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: Branch creation and rebasing will be limited to maximum ${commitHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`commitHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#commithourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < throttledBranchCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: PR creation will be limited to maximum ${prHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`prHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#prhourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n }\n return prDesc;\n}\n\n/**\n * Security update Pull Requests bypass the repository-wide `prConcurrentLimit`/`branchConcurrentLimit`\n * by default, but they can be rate limited on their own via `vulnerabilityAlerts.prConcurrentLimit`/\n * `branchConcurrentLimit`.\n *\n * - If the user has already opted in to that limit, and it would actually throttle the security updates,\n * say so - the \"not subject to this limit\" wording elsewhere refers only to the repository-wide limit.\n * - Otherwise, once the number of security updates alone would exceed the repository-wide limit, suggest\n * that the user may want to opt in to limiting them too.\n */\nfunction getSecurityConcurrentLimitNote(\n securityCount: number,\n concurrentLimit: number,\n vulnerabilityLimit: ConcurrentLimit,\n): string {\n if (securityCount === 0) {\n return '';\n }\n\n if (vulnerabilityLimit.limit > 0) {\n if (securityCount <= vulnerabilityLimit.limit) {\n return '';\n }\n return emojify(\n `:information_source: Renovate will only create ${vulnerabilityLimit.limit} security update Pull Request${vulnerabilityLimit.limit > 1 ? 's' : ''} at a time, up to a maximum of ${securityCount} over time, due to your [\\`vulnerabilityAlerts.${vulnerabilityLimit.key}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts) setting.\\n\\n`,\n );\n }\n\n if (concurrentLimit <= 0 || securityCount <= concurrentLimit) {\n return '';\n }\n return emojify(\n `:information_source: If you want to rate limit security update Pull Requests too, set [\\`vulnerabilityAlerts.prConcurrentLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts).\\n\\n`,\n );\n}\n\nfunction getBranchUpgradeTypes(branch: BranchConfig): Set<SummaryCategory> {\n if (branch.isVulnerabilityAlert) {\n return new Set(['security']);\n }\n const types = new Set<SummaryCategory>();\n for (const upgrade of branch.upgrades) {\n if (upgrade.updateType) {\n types.add(upgrade.updateType);\n } else if (upgrade.isLockfileUpdate) {\n types.add('lockfileUpdate');\n } else {\n types.add('other');\n }\n }\n return types;\n}\n\n// Sort: default branch (empty string) first, then named branches alphabetically.\nfunction sortBaseBranches(bases: Iterable<string>): string[] {\n return [...bases].sort((a, b) => {\n // v8 ignore if -- base branches are unique Record keys, so never equal\n if (a === b) {\n return 0;\n }\n if (a === '') {\n return -1;\n }\n if (b === '') {\n return 1;\n }\n return a.localeCompare(b);\n });\n}\n\nfunction describeSecurityGroup(groupBranches: BranchConfig[]): string {\n const firstUpgrade = groupBranches[0].upgrades[0];\n const depName = firstUpgrade?.depName ?? groupBranches[0].prTitle ?? '';\n const updateType = firstUpgrade?.updateType ?? 'unknown';\n const packageFiles = groupBranches\n .map((b) => ({ file: b.packageFile ?? '', manager: b.manager }))\n .filter((f) => f.file);\n const uniqueManagers = new Set(packageFiles.map((f) => f.manager));\n\n // Vulnerability alerts can match on datasource + packageName without a specific file (e.g. GitHub vulnerability alerts),\n // so we need to handle an absent packageFile\n if (packageFiles.length === 0) {\n const branchManagers = new Set(groupBranches.map((b) => b.manager));\n if (branchManagers.size === 1) {\n return `- \\`${depName}\\`, (${[...branchManagers][0]}, ${updateType})\\n`;\n }\n\n return `- \\`${depName}\\`, (${updateType}): ${[...branchManagers].sort().join(', ')}\\n`;\n }\n\n if (packageFiles.length === 1) {\n const file = packageFiles[0].file;\n const [manager] = uniqueManagers;\n return `- \\`${depName}\\`, (${manager}, ${updateType}): \\`${file}\\`\\n`;\n }\n\n if (uniqueManagers.size === 1) {\n const manager = [...uniqueManagers][0];\n const fileLines = packageFiles\n .map(({ file }) => ` - \\`${file}\\`\\n`)\n .join('');\n return `- \\`${depName}\\`, (${manager}, ${updateType}):\\n${fileLines}`;\n }\n\n const fileLines = packageFiles\n .map(({ file, manager }) => ` - \\`${file}\\` (${manager})\\n`)\n .join('');\n return `- \\`${depName}\\`, (${updateType}):\\n${fileLines}`;\n}\n\ninterface BranchStats {\n // PR count per base branch, deduplicated by branchName.\n prCountByBase: Record<string, number>;\n // base -> manager -> type -> count, deduplicated by branchName+manager+type.\n tableStats: Record<\n string,\n Record<string, Partial<Record<SummaryCategory, number>>>\n >;\n // All upgrade types seen anywhere — drives the table columns.\n presentCategories: Set<SummaryCategory>;\n // Security branches grouped by branchName.\n securityGroups: Record<string, BranchConfig[]>;\n prCount: number;\n}\n\nfunction collectBranchStats(branches: BranchConfig[]): BranchStats {\n const prCountByBase: Record<string, number> = {};\n const tableStats: Record<\n string,\n Record<string, Partial<Record<SummaryCategory, number>>>\n > = {};\n const presentTypes = new Set<SummaryCategory>();\n const securityGroups: Record<string, BranchConfig[]> = {};\n const seenPrs = new Set<string>();\n const seenTableKeys = new Set<string>();\n\n for (const branch of branches) {\n const base = branch.baseBranch ?? '';\n const { manager, branchName } = branch;\n const branchTypes = getBranchUpgradeTypes(branch);\n\n for (const type of branchTypes) {\n presentTypes.add(type);\n }\n\n if (!seenPrs.has(branchName)) {\n seenPrs.add(branchName);\n prCountByBase[base] = (prCountByBase[base] ?? 0) + 1;\n }\n\n tableStats[base] ??= {};\n const baseStats = tableStats[base];\n baseStats[manager] ??= {};\n const managerStats = baseStats[manager];\n for (const type of branchTypes) {\n const key = `${branchName}:${manager}:${type}`;\n if (seenTableKeys.has(key)) {\n continue;\n }\n seenTableKeys.add(key);\n managerStats[type] ??= 0;\n managerStats[type]++;\n }\n\n if (branch.isVulnerabilityAlert) {\n securityGroups[branchName] ??= [];\n securityGroups[branchName].push(branch);\n }\n }\n\n return {\n prCountByBase,\n tableStats,\n presentCategories: presentTypes,\n securityGroups,\n prCount: seenPrs.size,\n };\n}\n\nfunction getCategoryColumns(\n presentTypes: Set<SummaryCategory>,\n): SummaryCategory[] {\n const cols: SummaryCategory[] = SUMMARY_CATEGORY_PRIORITY_ORDER.filter((t) =>\n presentTypes.has(t),\n );\n // Append any present types not in the standard display order\n // (e.g. lockfileUpdate, bump).\n for (const t of presentTypes) {\n if (t !== 'other' && !cols.includes(t)) {\n cols.push(t);\n }\n }\n\n if (presentTypes.has('other')) {\n cols.push('other');\n }\n\n return cols;\n}\n\nfunction categoriesToColumnHeaders(cols: readonly string[]): string {\n /* v8 ignore next -- branches always have at least one upgrade, so cols is never empty in practice */\n if (cols.length === 0) {\n return '';\n }\n return ` | ${cols.join(' | ')}`;\n}\n\nfunction renderRowCounts(\n typeColumns: readonly SummaryCategory[],\n typeCounts: Partial<Record<SummaryCategory, number>>,\n): string {\n return categoriesToColumnHeaders(\n typeColumns.map((t) => `${typeCounts[t] ?? 0}`),\n );\n}\n\nfunction sumCategoryCounts(\n rows: Partial<Record<SummaryCategory, number>>[],\n categoryColumns: readonly SummaryCategory[],\n): Partial<Record<SummaryCategory, number>> {\n const sum: Partial<Record<SummaryCategory, number>> = {};\n for (const categoryCounts of rows) {\n for (const category of categoryColumns) {\n sum[category] = (sum[category] ?? 0) + (categoryCounts[category] ?? 0);\n }\n }\n return sum;\n}\n\nexport function getExpectedPrListSummary(\n config: RenovateConfig,\n branches: BranchConfig[],\n): string {\n logger.debug('getExpectedPrListSummary()');\n logger.trace({ config });\n let prDesc = `\\n### What to Expect\\n\\n`;\n if (!branches.length) {\n return `${prDesc}It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.\\n`;\n }\n\n const stats = collectBranchStats(branches);\n const sortedBases = sortBaseBranches(Object.keys(stats.prCountByBase));\n const hasMultipleBaseBranches = sortedBases.length > 1;\n\n const prHourlyLimit = coerceNumber(config.prHourlyLimit);\n const commitHourlyLimit = coerceNumber(config.commitHourlyLimit);\n const concurrentLimit = resolveConcurrentLimit(config);\n const vulnerabilityLimit = resolveVulnerabilityConcurrentLimit(config);\n // Vulnerability alert branches bypass the repository-wide rate/concurrency limits, so they shouldn't\n // count towards them - they get their own budget, see `resolveVulnerabilityConcurrentLimit()`.\n const securityCount = Object.keys(stats.securityGroups).length;\n\n if (hasMultipleBaseBranches) {\n let total = 0;\n const parts = sortedBases.map((base) => {\n const count = stats.prCountByBase[base];\n total += count;\n const label = base ? `the \\`${base}\\` branch` : 'the default branch';\n return `${count} Pull Request${count > 1 ? 's' : ''} to ${label}`;\n });\n const limitsNotice = determineLimitsNotice(\n concurrentLimit,\n prHourlyLimit,\n commitHourlyLimit,\n total - securityCount,\n securityCount,\n );\n prDesc += `With your current configuration, Renovate will create ${parts.join(' and ')}${limitsNotice}:\\n\\n`;\n } else {\n const limitsNotice = determineLimitsNotice(\n concurrentLimit,\n prHourlyLimit,\n commitHourlyLimit,\n stats.prCount - securityCount,\n securityCount,\n );\n prDesc += `With your current configuration, Renovate will create ${stats.prCount} Pull Request${stats.prCount > 1 ? 's' : ''}${limitsNotice}:\\n\\n`;\n }\n\n const categoryColumns = getCategoryColumns(stats.presentCategories);\n if (hasMultipleBaseBranches) {\n prDesc += `| Branch | Manager${categoriesToColumnHeaders(categoryColumns)} |\\n`;\n prDesc += `| --- | ---${categoryColumns.map(() => ' | ---').join('')} |\\n`;\n for (const base of sortedBases) {\n const label = base || '$default';\n for (const [manager, typeCounts] of Object.entries(\n stats.tableStats[base],\n )) {\n prDesc += `| ${label} | ${manager}${renderRowCounts(categoryColumns, typeCounts)} |\\n`;\n }\n }\n const sumRow = sumCategoryCounts(\n Object.values(stats.tableStats).flatMap((b) => Object.values(b)),\n categoryColumns,\n );\n prDesc += `| **Total** | ${renderRowCounts(categoryColumns, sumRow)} |\\n`;\n } else {\n prDesc += `| Manager${categoriesToColumnHeaders(categoryColumns)} |\\n`;\n prDesc += `| ---${categoryColumns.map(() => ' | ---').join('')} |\\n`;\n for (const [manager, typeCounts] of Object.entries(\n stats.tableStats[sortedBases[0]],\n )) {\n prDesc += `| ${manager}${renderRowCounts(categoryColumns, typeCounts)} |\\n`;\n }\n const sumRow = sumCategoryCounts(\n Object.values(stats.tableStats[sortedBases[0]]),\n categoryColumns,\n );\n prDesc += `| **Total**${renderRowCounts(categoryColumns, sumRow)} |\\n`;\n }\n\n prDesc += `\\n<small>Note that a single PR can update multiple files and/or managers, so the above rows may not align with the number of PRs being listed above.</small>\\n`;\n\n // provide a summary of the given security updates, as they're likely more important to the user\n if (Object.keys(stats.securityGroups).length) {\n prDesc += `\\n**Security updates**:\\n\\n`;\n for (const groupBranches of Object.values(stats.securityGroups)) {\n prDesc += describeSecurityGroup(groupBranches);\n }\n const securityConcurrentLimitNote = getSecurityConcurrentLimitNote(\n securityCount,\n concurrentLimit.limit,\n vulnerabilityLimit,\n );\n if (securityConcurrentLimitNote) {\n prDesc += `\\n${securityConcurrentLimitNote}`;\n }\n }\n\n const throttledPrCount = stats.prCount - securityCount;\n const securityBypassNote =\n securityCount > 0\n ? ` Security update Pull Request${securityCount > 1 ? 's are' : ' is'} not subject to this limit and will be created straight away.`\n : '';\n\n if (concurrentLimit.limit > 0 && concurrentLimit.limit < throttledPrCount) {\n const notice =\n concurrentLimit.key === 'branchConcurrentLimit'\n ? `Renovate will only work on ${concurrentLimit.limit} branch${concurrentLimit.limit > 1 ? 'es' : ''} at a time, so not all Pull Requests will be opened straight away`\n : `Renovate will only keep ${concurrentLimit.limit} Pull Request${concurrentLimit.limit > 1 ? 's' : ''} open at a time, so not all of the above will be opened straight away`;\n prDesc += emojify(\n `\\n\\n:children_crossing: ${notice}. See [docs for \\`${concurrentLimit.key}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#${concurrentLimit.key.toLowerCase()}) for details.${securityBypassNote}\\n\\n`,\n );\n }\n\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < throttledPrCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: Branch creation and rebasing will be limited to maximum ${commitHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`commitHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#commithourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < throttledPrCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: PR creation will be limited to maximum ${prHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`prHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#prhourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n }\n return prDesc;\n}\n\nfunction determineLimitsNotice(\n concurrentLimit: ConcurrentLimit,\n prHourlyLimit: number,\n commitHourlyLimit: number,\n prCount: number,\n securityCount: number,\n): string {\n const clauses: string[] = [];\n\n if (concurrentLimit.limit > 0 && concurrentLimit.limit < prCount) {\n clauses.push(\n concurrentLimit.key === 'branchConcurrentLimit'\n ? `a maximum of ${concurrentLimit.limit} branch${concurrentLimit.limit > 1 ? 'es' : ''} open at a time`\n : `a maximum of ${concurrentLimit.limit} Pull Request${concurrentLimit.limit > 1 ? 's' : ''} open at a time`,\n );\n }\n\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < prCount\n ) {\n clauses.push(\n `a maximum of ${commitHourlyLimit} PR${commitHourlyLimit > 1 ? 's' : ''}/rebase${commitHourlyLimit > 1 ? 's' : ''} per hour`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < prCount\n ) {\n clauses.push(\n `a maximum of ${prHourlyLimit} PR${prHourlyLimit > 1 ? 's' : ''} per hour`,\n );\n }\n\n if (!clauses.length) {\n if (commitHourlyLimit === 0 && prHourlyLimit === 0) {\n return ' (with no configured maximum of PRs per hour)';\n }\n return '';\n }\n\n const securityNote =\n securityCount > 0\n ? `, plus ${securityCount} security update${securityCount > 1 ? 's' : ''} which ${securityCount > 1 ? \"aren't\" : \"isn't\"} subject to these limits`\n : '';\n\n return emojify(` (at ${clauses.join(' and ')}${securityNote})`);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pr-list.js","names":[],"sources":["../../../../../lib/workers/repository/onboarding/pr/pr-list.ts"],"sourcesContent":["import { getDefault } from '../../../../config/defaults.ts';\nimport { GlobalConfig } from '../../../../config/global.ts';\nimport { getOptions } from '../../../../config/options/index.ts';\nimport {\n type RenovateConfig,\n type UpdateType,\n UpdateTypesOptions,\n} from '../../../../config/types.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { emojify } from '../../../../util/emoji.ts';\nimport { coerceNumber } from '../../../../util/number.ts';\nimport { regEx } from '../../../../util/regex.ts';\nimport { calcLimit } from '../../../global/limits.ts';\nimport type { BranchConfig, BranchUpgradeConfig } from '../../../types.ts';\n\n/**\n * The different categories of dependency updates to output, when providing the summary view.\n *\n * - `security`: if the upgrade is driven by a vulnerability alert\n * - `${updateType}`: if it's set. I.e. `major`\n * - `lockfileUpdate` when `isLockfileUpdate` is true, without an `updateType`\n * - `other`: otherwise\n */\ntype SummaryCategory = UpdateType | 'security' | 'other';\n\n/** Priority order when rendering the `SummaryCategory`s in the summary view.\n *\n * NOTE that this is not exhaustive - this is only the priority order for rendering, and other categories, such as `other` are placed after.\n */\nconst SUMMARY_CATEGORY_PRIORITY_ORDER: readonly SummaryCategory[] = [\n 'security',\n ...UpdateTypesOptions,\n // ... anything else\n];\n\ninterface ConcurrentLimit {\n limit: number;\n key: 'prConcurrentLimit' | 'branchConcurrentLimit';\n}\n\n/**\n * Resolves the concurrent limit that governs how many of the expected Pull Requests can be open at once,\n * reusing the same `calcLimit()` used to enforce these limits (see `lib/workers/global/limits.ts`).\n *\n * `branchConcurrentLimit` only takes priority when it's been explicitly configured (it's `null` by default,\n * in which case `calcLimit()` silently inherits the value of `prConcurrentLimit`) and is actually more\n * restrictive - otherwise we'd misattribute the limit to a setting the user never touched.\n */\nfunction resolveConcurrentLimit(config: RenovateConfig): ConcurrentLimit {\n const configAsUpgrade: BranchUpgradeConfig = {\n branchName: '',\n manager: '',\n prConcurrentLimit: config.prConcurrentLimit,\n branchConcurrentLimit: config.branchConcurrentLimit,\n };\n const prConcurrentLimit = calcLimit([configAsUpgrade], 'prConcurrentLimit');\n const branchConcurrentLimit = calcLimit(\n [configAsUpgrade],\n 'branchConcurrentLimit',\n );\n\n const isBelowPrLimit =\n prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit;\n if (\n typeof config.branchConcurrentLimit === 'number' &&\n branchConcurrentLimit > 0 &&\n isBelowPrLimit\n ) {\n return {\n limit: branchConcurrentLimit,\n key: 'branchConcurrentLimit',\n };\n }\n\n return { limit: prConcurrentLimit, key: 'prConcurrentLimit' };\n}\n\n/**\n * Vulnerability alert fixes get their own concurrent-limit budget via `vulnerabilityAlerts.prConcurrentLimit`/ `vulnerabilityAlerts.branchConcurrentLimit`, separate from repository-wide/dependency-specific rules.\n * Falls back to the `vulnerabilityAlerts` option's own schema default (currently `0`, i.e. no limit) when\n * unset, via `getDefault()`, rather than duplicating that value here.\n */\nfunction resolveVulnerabilityConcurrentLimit(\n config: RenovateConfig,\n): ConcurrentLimit {\n // `vulnerabilityAlerts` is typed as `RenovateSharedConfig`, which doesn't declare `prConcurrentLimit`/\n // `branchConcurrentLimit`, even though both are valid nested options (see docs for `vulnerabilityAlerts`).\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion\n const vulnerabilityAlerts = config.vulnerabilityAlerts as\n RenovateConfig | undefined;\n const vulnerabilityAlertsDefault = getDefault(\n getOptions().find((option) => option.name === 'vulnerabilityAlerts')!,\n ) as RenovateConfig;\n const configAsUpgrade: BranchUpgradeConfig = {\n branchName: '',\n manager: '',\n prConcurrentLimit:\n vulnerabilityAlerts?.prConcurrentLimit ??\n vulnerabilityAlertsDefault.prConcurrentLimit,\n // `undefined` and `null` are handled identically by `calcLimit()` (both inherit `prConcurrentLimit`),\n // so there's no default value to duplicate here - unlike `prConcurrentLimit` above.\n branchConcurrentLimit: vulnerabilityAlerts?.branchConcurrentLimit,\n };\n const prConcurrentLimit = calcLimit([configAsUpgrade], 'prConcurrentLimit');\n const branchConcurrentLimit = calcLimit(\n [configAsUpgrade],\n 'branchConcurrentLimit',\n );\n\n const isBelowPrLimit =\n prConcurrentLimit === 0 || branchConcurrentLimit < prConcurrentLimit;\n if (\n typeof vulnerabilityAlerts?.branchConcurrentLimit === 'number' &&\n branchConcurrentLimit > 0 &&\n isBelowPrLimit\n ) {\n return {\n limit: branchConcurrentLimit,\n key: 'branchConcurrentLimit',\n };\n }\n\n return { limit: prConcurrentLimit, key: 'prConcurrentLimit' };\n}\n\nexport function getExpectedPrList(\n config: RenovateConfig,\n branches: BranchConfig[],\n): string {\n logger.debug('getExpectedPrList()');\n logger.trace({ config });\n let prDesc = `\\n### What to Expect\\n\\n`;\n if (!branches.length) {\n return `${prDesc}It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.\\n`;\n }\n // Vulnerability alert branches bypass the repository-wide rate/concurrency limits, so they shouldn't\n // count towards them - they get their own budget, see `resolveVulnerabilityConcurrentLimit()`.\n const securityBranchCount = branches.filter(\n (b) => b.isVulnerabilityAlert,\n ).length;\n const throttledBranchCount = branches.length - securityBranchCount;\n\n const { limit: concurrentLimit, key: concurrentLimitKey } =\n resolveConcurrentLimit(config);\n if (concurrentLimit > 0 && concurrentLimit < throttledBranchCount) {\n const securityNote =\n securityBranchCount > 0\n ? `, plus ${securityBranchCount} security update Pull Request${securityBranchCount > 1 ? 's' : ''} which ${securityBranchCount > 1 ? 'are' : 'is'} not subject to this limit`\n : '';\n prDesc += `With your current configuration, Renovate will create ${concurrentLimit} Pull Request${concurrentLimit > 1 ? 's' : ''}, up to a maximum of ${branches.length} over time (see [docs for \\`${concurrentLimitKey}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#${concurrentLimitKey.toLowerCase()}))${securityNote}:\\n\\n`;\n } else {\n prDesc += `With your current configuration, Renovate will create ${branches.length} Pull Request`;\n prDesc += branches.length > 1 ? `s:\\n\\n` : `:\\n\\n`;\n }\n prDesc += getSecurityConcurrentLimitNote(\n securityBranchCount,\n concurrentLimit,\n resolveVulnerabilityConcurrentLimit(config),\n );\n\n for (const branch of branches) {\n const prTitleRe = regEx(/@(?<scope>[a-z]+\\/[a-z]+)/);\n // TODO #22198\n prDesc += `<details>\\n<summary>${branch.prTitle!.replace(\n prTitleRe,\n '@​$<scope>',\n )}</summary>\\n\\n`;\n if (branch.schedule?.length) {\n prDesc += ` - Schedule: ${JSON.stringify(branch.schedule)}\\n`;\n }\n prDesc += ` - Branch name: \\`${branch.branchName}\\`\\n`;\n prDesc += branch.baseBranch\n ? ` - Merge into: \\`${branch.baseBranch}\\`\\n`\n : '';\n const seen: string[] = [];\n for (const upgrade of branch.upgrades) {\n let text = '';\n if (upgrade.updateType === 'lockFileMaintenance') {\n text += ' - Regenerate lock files to use latest dependency versions';\n } else {\n if (upgrade.updateType === 'pin') {\n text += ' - Pin ';\n } else {\n text += ' - Upgrade ';\n }\n if (upgrade.sourceUrl) {\n // TODO: types (#22198)\n text += `[${upgrade.depName!}](${upgrade.sourceUrl})`;\n } else {\n text += upgrade.depName!.replace(prTitleRe, '@​$1');\n }\n // TODO: types (#22198)\n text += upgrade.isLockfileUpdate\n ? ` to \\`${upgrade.newVersion!}\\``\n : ` to \\`${upgrade.newDigest ?? upgrade.newValue!}\\``;\n text += '\\n';\n }\n if (!seen.includes(text)) {\n prDesc += text;\n seen.push(text);\n }\n }\n prDesc += '\\n\\n';\n prDesc += '</details>\\n\\n';\n }\n const prHourlyLimit = coerceNumber(config.prHourlyLimit);\n const commitHourlyLimit = coerceNumber(config.commitHourlyLimit);\n const securityBypassNote =\n securityBranchCount > 0\n ? ` Security update Pull Request${securityBranchCount > 1 ? 's are' : ' is'} not subject to this limit and will be created straight away.`\n : '';\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < throttledBranchCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: Branch creation and rebasing will be limited to maximum ${commitHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`commitHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#commithourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < throttledBranchCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: PR creation will be limited to maximum ${prHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`prHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#prhourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n }\n return prDesc;\n}\n\n/**\n * Security update Pull Requests bypass the repository-wide `prConcurrentLimit`/`branchConcurrentLimit`\n * by default, but they can be rate limited on their own via `vulnerabilityAlerts.prConcurrentLimit`/\n * `branchConcurrentLimit`.\n *\n * - If the user has already opted in to that limit, and it would actually throttle the security updates,\n * say so - the \"not subject to this limit\" wording elsewhere refers only to the repository-wide limit.\n * - Otherwise, once the number of security updates alone would exceed the repository-wide limit, suggest\n * that the user may want to opt in to limiting them too.\n */\nfunction getSecurityConcurrentLimitNote(\n securityCount: number,\n concurrentLimit: number,\n vulnerabilityLimit: ConcurrentLimit,\n): string {\n if (securityCount === 0) {\n return '';\n }\n\n if (vulnerabilityLimit.limit > 0) {\n if (securityCount <= vulnerabilityLimit.limit) {\n return '';\n }\n return emojify(\n `:information_source: Renovate will only create ${vulnerabilityLimit.limit} security update Pull Request${vulnerabilityLimit.limit > 1 ? 's' : ''} at a time, up to a maximum of ${securityCount} over time, due to your [\\`vulnerabilityAlerts.${vulnerabilityLimit.key}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts) setting.\\n\\n`,\n );\n }\n\n if (concurrentLimit <= 0 || securityCount <= concurrentLimit) {\n return '';\n }\n return emojify(\n `:information_source: If you want to rate limit security update Pull Requests too, set [\\`vulnerabilityAlerts.prConcurrentLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts).\\n\\n`,\n );\n}\n\nfunction getBranchUpgradeTypes(branch: BranchConfig): Set<SummaryCategory> {\n if (branch.isVulnerabilityAlert) {\n return new Set(['security']);\n }\n const types = new Set<SummaryCategory>();\n for (const upgrade of branch.upgrades) {\n if (upgrade.updateType) {\n types.add(upgrade.updateType);\n } else if (upgrade.isLockfileUpdate) {\n types.add('lockfileUpdate');\n } else {\n types.add('other');\n }\n }\n return types;\n}\n\n// Sort: default branch (empty string) first, then named branches alphabetically.\nfunction sortBaseBranches(bases: Iterable<string>): string[] {\n return [...bases].sort((a, b) => {\n // v8 ignore if -- base branches are unique Record keys, so never equal\n if (a === b) {\n return 0;\n }\n if (a === '') {\n return -1;\n }\n if (b === '') {\n return 1;\n }\n return a.localeCompare(b);\n });\n}\n\nfunction describeSecurityGroup(groupBranches: BranchConfig[]): string {\n const firstUpgrade = groupBranches[0].upgrades[0];\n const depName = firstUpgrade?.depName ?? groupBranches[0].prTitle ?? '';\n const updateType = firstUpgrade?.updateType ?? 'unknown';\n const packageFiles = groupBranches\n .map((b) => ({ file: b.packageFile ?? '', manager: b.manager }))\n .filter((f) => f.file);\n const uniqueManagers = new Set(packageFiles.map((f) => f.manager));\n\n // Vulnerability alerts can match on datasource + packageName without a specific file (e.g. GitHub vulnerability alerts),\n // so we need to handle an absent packageFile\n if (packageFiles.length === 0) {\n const branchManagers = new Set(groupBranches.map((b) => b.manager));\n if (branchManagers.size === 1) {\n return `- \\`${depName}\\`, (${[...branchManagers][0]}, ${updateType})\\n`;\n }\n\n return `- \\`${depName}\\`, (${updateType}): ${[...branchManagers].sort().join(', ')}\\n`;\n }\n\n if (packageFiles.length === 1) {\n const file = packageFiles[0].file;\n const [manager] = uniqueManagers;\n return `- \\`${depName}\\`, (${manager}, ${updateType}): \\`${file}\\`\\n`;\n }\n\n if (uniqueManagers.size === 1) {\n const manager = [...uniqueManagers][0];\n const fileLines = packageFiles\n .map(({ file }) => ` - \\`${file}\\`\\n`)\n .join('');\n return `- \\`${depName}\\`, (${manager}, ${updateType}):\\n${fileLines}`;\n }\n\n const fileLines = packageFiles\n .map(({ file, manager }) => ` - \\`${file}\\` (${manager})\\n`)\n .join('');\n return `- \\`${depName}\\`, (${updateType}):\\n${fileLines}`;\n}\n\ninterface BranchStats {\n // PR count per base branch, deduplicated by branchName.\n prCountByBase: Record<string, number>;\n // base -> manager -> type -> count, deduplicated by branchName+manager+type.\n tableStats: Record<\n string,\n Record<string, Partial<Record<SummaryCategory, number>>>\n >;\n // All upgrade types seen anywhere — drives the table columns.\n presentCategories: Set<SummaryCategory>;\n // Security branches grouped by branchName.\n securityGroups: Record<string, BranchConfig[]>;\n prCount: number;\n}\n\nfunction collectBranchStats(branches: BranchConfig[]): BranchStats {\n const prCountByBase: Record<string, number> = {};\n const tableStats: Record<\n string,\n Record<string, Partial<Record<SummaryCategory, number>>>\n > = {};\n const presentTypes = new Set<SummaryCategory>();\n const securityGroups: Record<string, BranchConfig[]> = {};\n const seenPrs = new Set<string>();\n const seenTableKeys = new Set<string>();\n\n for (const branch of branches) {\n const base = branch.baseBranch ?? '';\n const { manager, branchName } = branch;\n const branchTypes = getBranchUpgradeTypes(branch);\n\n for (const type of branchTypes) {\n presentTypes.add(type);\n }\n\n if (!seenPrs.has(branchName)) {\n seenPrs.add(branchName);\n prCountByBase[base] = (prCountByBase[base] ?? 0) + 1;\n }\n\n tableStats[base] ??= {};\n const baseStats = tableStats[base];\n baseStats[manager] ??= {};\n const managerStats = baseStats[manager];\n for (const type of branchTypes) {\n const key = `${branchName}:${manager}:${type}`;\n if (seenTableKeys.has(key)) {\n continue;\n }\n seenTableKeys.add(key);\n managerStats[type] ??= 0;\n managerStats[type]++;\n }\n\n if (branch.isVulnerabilityAlert) {\n securityGroups[branchName] ??= [];\n securityGroups[branchName].push(branch);\n }\n }\n\n return {\n prCountByBase,\n tableStats,\n presentCategories: presentTypes,\n securityGroups,\n prCount: seenPrs.size,\n };\n}\n\nfunction getCategoryColumns(\n presentTypes: Set<SummaryCategory>,\n): SummaryCategory[] {\n const cols: SummaryCategory[] = SUMMARY_CATEGORY_PRIORITY_ORDER.filter((t) =>\n presentTypes.has(t),\n );\n // Append any present types not in the standard display order\n // (e.g. lockfileUpdate, bump).\n for (const t of presentTypes) {\n if (t !== 'other' && !cols.includes(t)) {\n cols.push(t);\n }\n }\n\n if (presentTypes.has('other')) {\n cols.push('other');\n }\n\n return cols;\n}\n\nfunction categoriesToColumnHeaders(cols: readonly string[]): string {\n /* v8 ignore next -- branches always have at least one upgrade, so cols is never empty in practice */\n if (cols.length === 0) {\n return '';\n }\n return ` | ${cols.join(' | ')}`;\n}\n\nfunction renderRowCounts(\n typeColumns: readonly SummaryCategory[],\n typeCounts: Partial<Record<SummaryCategory, number>>,\n): string {\n return categoriesToColumnHeaders(\n typeColumns.map((t) => `${typeCounts[t] ?? 0}`),\n );\n}\n\nfunction sumCategoryCounts(\n rows: Partial<Record<SummaryCategory, number>>[],\n categoryColumns: readonly SummaryCategory[],\n): Partial<Record<SummaryCategory, number>> {\n const sum: Partial<Record<SummaryCategory, number>> = {};\n for (const categoryCounts of rows) {\n for (const category of categoryColumns) {\n sum[category] = (sum[category] ?? 0) + (categoryCounts[category] ?? 0);\n }\n }\n return sum;\n}\n\nexport function getExpectedPrListSummary(\n config: RenovateConfig,\n branches: BranchConfig[],\n): string {\n logger.debug('getExpectedPrListSummary()');\n logger.trace({ config });\n let prDesc = `\\n### What to Expect\\n\\n`;\n if (!branches.length) {\n return `${prDesc}It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.\\n`;\n }\n\n const stats = collectBranchStats(branches);\n const sortedBases = sortBaseBranches(Object.keys(stats.prCountByBase));\n const hasMultipleBaseBranches = sortedBases.length > 1;\n\n const prHourlyLimit = coerceNumber(config.prHourlyLimit);\n const commitHourlyLimit = coerceNumber(config.commitHourlyLimit);\n const concurrentLimit = resolveConcurrentLimit(config);\n const vulnerabilityLimit = resolveVulnerabilityConcurrentLimit(config);\n // Vulnerability alert branches bypass the repository-wide rate/concurrency limits, so they shouldn't\n // count towards them - they get their own budget, see `resolveVulnerabilityConcurrentLimit()`.\n const securityCount = Object.keys(stats.securityGroups).length;\n\n if (hasMultipleBaseBranches) {\n let total = 0;\n const parts = sortedBases.map((base) => {\n const count = stats.prCountByBase[base];\n total += count;\n const label = base ? `the \\`${base}\\` branch` : 'the default branch';\n return `${count} Pull Request${count > 1 ? 's' : ''} to ${label}`;\n });\n const limitsNotice = determineLimitsNotice(\n concurrentLimit,\n prHourlyLimit,\n commitHourlyLimit,\n total - securityCount,\n securityCount,\n );\n prDesc += `With your current configuration, Renovate will create ${parts.join(' and ')}${limitsNotice}:\\n\\n`;\n } else {\n const limitsNotice = determineLimitsNotice(\n concurrentLimit,\n prHourlyLimit,\n commitHourlyLimit,\n stats.prCount - securityCount,\n securityCount,\n );\n prDesc += `With your current configuration, Renovate will create ${stats.prCount} Pull Request${stats.prCount > 1 ? 's' : ''}${limitsNotice}:\\n\\n`;\n }\n\n const categoryColumns = getCategoryColumns(stats.presentCategories);\n if (hasMultipleBaseBranches) {\n prDesc += `| Branch | Manager${categoriesToColumnHeaders(categoryColumns)} |\\n`;\n prDesc += `| --- | ---${categoryColumns.map(() => ' | ---').join('')} |\\n`;\n for (const base of sortedBases) {\n const label = base || '$default';\n for (const [manager, typeCounts] of Object.entries(\n stats.tableStats[base],\n )) {\n prDesc += `| ${label} | ${manager}${renderRowCounts(categoryColumns, typeCounts)} |\\n`;\n }\n }\n const sumRow = sumCategoryCounts(\n Object.values(stats.tableStats).flatMap((b) => Object.values(b)),\n categoryColumns,\n );\n prDesc += `| **Total** | ${renderRowCounts(categoryColumns, sumRow)} |\\n`;\n } else {\n prDesc += `| Manager${categoriesToColumnHeaders(categoryColumns)} |\\n`;\n prDesc += `| ---${categoryColumns.map(() => ' | ---').join('')} |\\n`;\n for (const [manager, typeCounts] of Object.entries(\n stats.tableStats[sortedBases[0]],\n )) {\n prDesc += `| ${manager}${renderRowCounts(categoryColumns, typeCounts)} |\\n`;\n }\n const sumRow = sumCategoryCounts(\n Object.values(stats.tableStats[sortedBases[0]]),\n categoryColumns,\n );\n prDesc += `| **Total**${renderRowCounts(categoryColumns, sumRow)} |\\n`;\n }\n\n prDesc += `\\n<small>Note that a single PR can update multiple files and/or managers, so the above rows may not align with the number of PRs being listed above.</small>\\n`;\n\n // provide a summary of the given security updates, as they're likely more important to the user\n if (Object.keys(stats.securityGroups).length) {\n prDesc += `\\n**Security updates**:\\n\\n`;\n for (const groupBranches of Object.values(stats.securityGroups)) {\n prDesc += describeSecurityGroup(groupBranches);\n }\n const securityConcurrentLimitNote = getSecurityConcurrentLimitNote(\n securityCount,\n concurrentLimit.limit,\n vulnerabilityLimit,\n );\n if (securityConcurrentLimitNote) {\n prDesc += `\\n${securityConcurrentLimitNote}`;\n }\n }\n\n const throttledPrCount = stats.prCount - securityCount;\n const securityBypassNote =\n securityCount > 0\n ? ` Security update Pull Request${securityCount > 1 ? 's are' : ' is'} not subject to this limit and will be created straight away.`\n : '';\n\n if (concurrentLimit.limit > 0 && concurrentLimit.limit < throttledPrCount) {\n const notice =\n concurrentLimit.key === 'branchConcurrentLimit'\n ? `Renovate will only work on ${concurrentLimit.limit} branch${concurrentLimit.limit > 1 ? 'es' : ''} at a time, so not all Pull Requests will be opened straight away`\n : `Renovate will only keep ${concurrentLimit.limit} Pull Request${concurrentLimit.limit > 1 ? 's' : ''} open at a time, so not all of the above will be opened straight away`;\n prDesc += emojify(\n `\\n\\n:children_crossing: ${notice}. See [docs for \\`${concurrentLimit.key}\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#${concurrentLimit.key.toLowerCase()}) for details.${securityBypassNote}\\n\\n`,\n );\n }\n\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < throttledPrCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: Branch creation and rebasing will be limited to maximum ${commitHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`commitHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#commithourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < throttledPrCount\n ) {\n prDesc += emojify(\n `\\n\\n:children_crossing: PR creation will be limited to maximum ${prHourlyLimit} per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for \\`prHourlyLimit\\`](${GlobalConfig.get('productLinks').documentation}configuration-options/#prhourlylimit) for details.${securityBypassNote}\\n\\n`,\n );\n }\n return prDesc;\n}\n\nfunction determineLimitsNotice(\n concurrentLimit: ConcurrentLimit,\n prHourlyLimit: number,\n commitHourlyLimit: number,\n prCount: number,\n securityCount: number,\n): string {\n const clauses: string[] = [];\n\n if (concurrentLimit.limit > 0 && concurrentLimit.limit < prCount) {\n clauses.push(\n concurrentLimit.key === 'branchConcurrentLimit'\n ? `a maximum of ${concurrentLimit.limit} branch${concurrentLimit.limit > 1 ? 'es' : ''} open at a time`\n : `a maximum of ${concurrentLimit.limit} Pull Request${concurrentLimit.limit > 1 ? 's' : ''} open at a time`,\n );\n }\n\n if (\n commitHourlyLimit > 0 &&\n commitHourlyLimit < 5 &&\n commitHourlyLimit < prCount\n ) {\n clauses.push(\n `a maximum of ${commitHourlyLimit} PR${commitHourlyLimit > 1 ? 's' : ''}/rebase${commitHourlyLimit > 1 ? 's' : ''} per hour`,\n );\n } else if (\n prHourlyLimit > 0 &&\n prHourlyLimit < 5 &&\n prHourlyLimit < prCount\n ) {\n clauses.push(\n `a maximum of ${prHourlyLimit} PR${prHourlyLimit > 1 ? 's' : ''} per hour`,\n );\n }\n\n if (!clauses.length) {\n if (commitHourlyLimit === 0 && prHourlyLimit === 0) {\n return ' (with no configured maximum of PRs per hour)';\n }\n return '';\n }\n\n const securityNote =\n securityCount > 0\n ? `, plus ${securityCount} security update${securityCount > 1 ? 's' : ''} which ${securityCount > 1 ? \"aren't\" : \"isn't\"} subject to these limits`\n : '';\n\n return emojify(` (at ${clauses.join(' and ')}${securityNote})`);\n}\n"],"mappings":"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"}
|
|
@@ -101,7 +101,10 @@ async function extract(config, overwriteCache = true) {
|
|
|
101
101
|
const { extractionFingerprints } = extractResult;
|
|
102
102
|
const registryUrlsHadCredentials = detachRegistryUrlCredentials(packageFiles);
|
|
103
103
|
const cachedPackageFiles = overwriteCache ? withoutNpmrc(packageFiles) : void 0;
|
|
104
|
-
|
|
104
|
+
function hasCredentials() {
|
|
105
|
+
return registryUrlsHadCredentials || containsUrlCredentials(cachedPackageFiles);
|
|
106
|
+
}
|
|
107
|
+
if (overwriteCache && hasCredentials()) {
|
|
105
108
|
logger.once.warn({ baseBranch }, "The package files contain URLs with credentials, so the extract result is not cached: configure the credentials through hostRules instead");
|
|
106
109
|
delete cache.scan[baseBranch];
|
|
107
110
|
} else if (cachedPackageFiles) cache.scan[baseBranch] = {
|