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
|
@@ -7,6 +7,7 @@ import { coerceArray } from "../../../util/array.js";
|
|
|
7
7
|
import { sanitize } from "../../../util/sanitize.js";
|
|
8
8
|
import { logger } from "../../../logger/index.js";
|
|
9
9
|
import { ensureTrailingSlash, getQueryString, parseUrl } from "../../../util/url.js";
|
|
10
|
+
import { isForbidden, isNotAcceptable, isNotFound, isUnauthorized } from "../../../util/http/status.js";
|
|
10
11
|
import { noLeadingAtSymbol, parseJson } from "../../../util/common.js";
|
|
11
12
|
import { parseInteger } from "../../../util/number.js";
|
|
12
13
|
import { all } from "../../../util/promises.js";
|
|
@@ -202,8 +203,8 @@ async function initRepo({ repository, cloneSubmodules, cloneSubmodulesFilter, gi
|
|
|
202
203
|
"empty",
|
|
203
204
|
"pending-deletion"
|
|
204
205
|
].includes(err.message)) throw err;
|
|
205
|
-
if (err
|
|
206
|
-
if (err
|
|
206
|
+
if (isForbidden(err)) throw new Error(REPOSITORY_ACCESS_FORBIDDEN);
|
|
207
|
+
if (isNotFound(err)) throw new Error(REPOSITORY_NOT_FOUND);
|
|
207
208
|
if (err.message === "disabled") throw err;
|
|
208
209
|
logger.debug({ err }, "Unknown GitLab initRepo error");
|
|
209
210
|
throw err;
|
|
@@ -238,7 +239,7 @@ async function isPrInMergeQueue(id) {
|
|
|
238
239
|
const { body: status } = await gitlabApi.getJson(`projects/${config.repository}/merge_trains/merge_requests/${id}`, { memCache: false }, MergeTrainCarStatus);
|
|
239
240
|
return status !== "merged";
|
|
240
241
|
} catch (err) {
|
|
241
|
-
if (err
|
|
242
|
+
if (!isNotFound(err)) logger.debug({ err }, "Failed to fetch merge train status");
|
|
242
243
|
return false;
|
|
243
244
|
}
|
|
244
245
|
}
|
|
@@ -251,7 +252,7 @@ async function getStatus(branchName, useCache = true, sha = getBranchCommit(bran
|
|
|
251
252
|
return (await gitlabApi.getJsonUnchecked(url, opts)).body;
|
|
252
253
|
} catch (err) /* v8 ignore next -- commit status fetch failures map 404 to REPOSITORY_CHANGED, not mocked in specs */ {
|
|
253
254
|
logger.debug({ err }, "Error getting commit status");
|
|
254
|
-
if (err
|
|
255
|
+
if (isNotFound(err)) throw new Error(REPOSITORY_CHANGED);
|
|
255
256
|
throw err;
|
|
256
257
|
}
|
|
257
258
|
}
|
|
@@ -290,7 +291,10 @@ async function getBranchStatus(branchName, internalChecksAsSuccess) {
|
|
|
290
291
|
}
|
|
291
292
|
const res = branchStatuses.filter((check) => check.status !== "skipped");
|
|
292
293
|
if (res.length === 0) return "yellow";
|
|
293
|
-
if (!internalChecksAsSuccess && branchStatuses.every((check) =>
|
|
294
|
+
if (!internalChecksAsSuccess && branchStatuses.every((check) => {
|
|
295
|
+
const isGreen = gitlabToRenovateStatusMapping[check.status] === "green";
|
|
296
|
+
return check.name?.startsWith("renovate/") && isGreen;
|
|
297
|
+
})) {
|
|
294
298
|
logger.debug("Successful checks are all internal renovate/ checks, so returning \"pending\" branch status");
|
|
295
299
|
return "yellow";
|
|
296
300
|
}
|
|
@@ -462,11 +466,11 @@ async function mergePr({ id }) {
|
|
|
462
466
|
await gitlabApi.putJson(`projects/${config.repository}/merge_requests/${id}/merge`, { body: { should_remove_source_branch: true } });
|
|
463
467
|
return true;
|
|
464
468
|
} catch (err) /* v8 ignore next -- merge rejection statuses (401/406) are mapped to false, not mocked in specs */ {
|
|
465
|
-
if (err
|
|
469
|
+
if (isUnauthorized(err)) {
|
|
466
470
|
logger.debug("No permissions to merge PR");
|
|
467
471
|
return false;
|
|
468
472
|
}
|
|
469
|
-
if (err
|
|
473
|
+
if (isNotAcceptable(err)) {
|
|
470
474
|
logger.debug({ err }, "PR not acceptable for merging");
|
|
471
475
|
return false;
|
|
472
476
|
}
|
|
@@ -505,7 +509,10 @@ async function findPr({ branchName, prTitle, state = "all", includeOtherAuthors
|
|
|
505
509
|
}
|
|
506
510
|
return prInfo(mrList[0]);
|
|
507
511
|
}
|
|
508
|
-
return (await getPrList()).find((p) =>
|
|
512
|
+
return (await getPrList()).find((p) => {
|
|
513
|
+
if (p.sourceBranch !== branchName || !matchesState(p.state, state)) return false;
|
|
514
|
+
return !prTitle || p.title.toUpperCase() === prTitle.toUpperCase();
|
|
515
|
+
}) ?? null;
|
|
509
516
|
}
|
|
510
517
|
async function getBranchPr(branchName) {
|
|
511
518
|
logger.debug(`getBranchPr(${branchName})`);
|
|
@@ -882,7 +889,7 @@ async function expandGroupMembers(reviewersOrAssignees) {
|
|
|
882
889
|
const members = await getMemberUsernames(reviewerOrAssignee);
|
|
883
890
|
expandedReviewersOrAssignees.push(...members);
|
|
884
891
|
} catch (err) {
|
|
885
|
-
if (err
|
|
892
|
+
if (!isNotFound(err)) logger.debug({
|
|
886
893
|
err,
|
|
887
894
|
reviewerOrAssignee
|
|
888
895
|
}, "Unable to fetch group");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["git.initRepo","git.getBranchCommit","git.branchExists","p.all"],"sources":["../../../../lib/modules/platform/gitlab/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport {\n isArray,\n isEmptyArray,\n isNonEmptyArray,\n isString,\n} from '@sindresorhus/is';\nimport pMap from 'p-map';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n REPOSITORY_NOT_FOUND,\n REPOSITORY_PENDING_DELETION,\n TEMPORARY_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { noLeadingAtSymbol, parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { GitlabHttpOptions } from '../../../util/http/gitlab.ts';\nimport { setBaseUrl } from '../../../util/http/gitlab.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { parseInteger } from '../../../util/number.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { EmailAddress } from '../../../util/schema-utils/index.ts';\nimport {\n ensureTrailingSlash,\n getQueryString,\n parseUrl,\n} from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { getRepoFile } from './files.ts';\nimport {\n getMemberUserIDs,\n getMemberUsernames,\n getProjectMembersByRole,\n getUserID,\n gitlabApi,\n isUserBusy,\n} from './http.ts';\nimport { getMR, updateMR } from './merge-request.ts';\nimport { GitlabPrCache } from './pr-cache.ts';\nimport { getRoleAccessLevel } from './roles.ts';\nimport type { GitLabMergeRequest } from './schema.ts';\nimport { LastPipelineId, MergeTrainCarStatus } from './schema.ts';\nimport type {\n GitlabComment,\n GitlabIssue,\n GitlabPr,\n MergeMethod,\n RepoResponse,\n} from './types.ts';\nimport {\n DRAFT_PREFIX,\n DRAFT_PREFIX_DEPRECATED,\n defaults,\n getRepoUrl,\n prInfo,\n} from './utils.ts';\n\nexport { extractRulesFromCodeOwnersLines } from './code-owners.ts';\n\nlet config: {\n repository: string;\n email: EmailAddress;\n issueList: GitlabIssue[] | undefined;\n mergeMethod: MergeMethod;\n mergeTrainsEnabled: boolean;\n defaultBranch: string;\n cloneSubmodules: boolean | undefined;\n cloneSubmodulesFilter: string[] | undefined;\n ignorePrAuthor: boolean | undefined;\n squash: boolean;\n} = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n draftPrefix = DRAFT_PREFIX;\n defaults.hostType = 'gitlab';\n defaults.endpoint = 'https://gitlab.com/api/v4/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nexport const id = 'gitlab';\n\nlet draftPrefix = DRAFT_PREFIX;\nlet botUserName: string;\n\nexport async function initPlatform({\n endpoint,\n username,\n token,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error('Init: You must configure a GitLab personal access token');\n }\n if (!endpoint) {\n logger.debug(`Using default GitLab endpoint: ${defaults.endpoint}`);\n } else if (parseUrl(endpoint) === null) {\n throw new Error(`Invalid GitLab endpoint URL: ${endpoint}`);\n } else {\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n }\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n let gitlabVersion: string;\n try {\n if (!gitAuthor) {\n const user = (\n await gitlabApi.getJsonUnchecked<{\n email: EmailAddress;\n name: string;\n id: number;\n commit_email?: EmailAddress;\n }>(`user`, { token })\n ).body;\n platformConfig.gitAuthor = `${user.name} <${\n user.commit_email ?? user.email\n }>`;\n botUserName = user.name;\n }\n const env = getEnv();\n /* v8 ignore next: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gitlabVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n const version = (\n await gitlabApi.getJsonUnchecked<{ version: string }>('version', {\n token,\n })\n ).body;\n gitlabVersion = version.version;\n }\n logger.debug(`GitLab version is: ${gitlabVersion}`);\n // version is 'x.y.z-edition', so not strictly semver; need to strip edition\n [gitlabVersion] = gitlabVersion.split('-');\n defaults.version = gitlabVersion;\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with GitLab. Check that your token includes \"api\" permissions',\n );\n throw new Error('Init: Authentication failure');\n }\n draftPrefix = semver.lt(defaults.version, '13.2.0')\n ? DRAFT_PREFIX_DEPRECATED\n : DRAFT_PREFIX;\n\n botUserName ??= username!;\n\n return platformConfig;\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering GitLab repositories');\n\n const queryParams: Record<string, any> = {\n membership: true,\n per_page: 100,\n with_merge_requests_enabled: true,\n min_access_level: 30,\n archived: false,\n ...(config?.sort && { order_by: config.sort }),\n ...(config?.order && { sort: config.order }),\n };\n if (config?.topics?.length) {\n queryParams.topic = config.topics.join(',');\n }\n\n const urls = [];\n if (config?.namespaces?.length) {\n queryParams.with_shared = false;\n queryParams.include_subgroups = true;\n urls.push(\n ...config.namespaces.map(\n (namespace) =>\n `groups/${urlEscape(namespace)}/projects?${getQueryString(\n queryParams,\n )}`,\n ),\n );\n } else {\n urls.push(`projects?${getQueryString(queryParams)}`);\n }\n\n try {\n const repos = (\n await pMap(\n urls,\n (url) =>\n gitlabApi.getJsonUnchecked<RepoResponse[]>(url, {\n paginate: true,\n }),\n {\n concurrency: 2,\n },\n )\n ).flatMap((response) => response.body);\n\n logger.debug(`Discovered ${repos.length} project(s)`);\n return repos\n .filter((repo) => !repo.mirror || config?.includeMirrors)\n .filter((repo) => !repo.marked_for_deletion_at)\n .map((repo) => repo.path_with_namespace);\n } catch (err) {\n logger.error({ err }, `GitLab getRepos error`);\n throw err;\n }\n}\n\nfunction urlEscape(str: string): string;\nfunction urlEscape(str: string | undefined): string | undefined;\nfunction urlEscape(str: string | undefined): string | undefined {\n return str?.replace(regEx(/\\//g), '%2F');\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = urlEscape(repoName) ?? config.repository;\n return await getRepoFile(gitlabApi, repo, fileName, branchOrTag, {\n cacheProvider: memCacheProvider,\n });\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize GitLab by getting base branch\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n config = {} as any;\n config.repository = urlEscape(repository);\n config.cloneSubmodules = cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n let res: HttpResponse<RepoResponse>;\n try {\n res = await gitlabApi.getJsonUnchecked<RepoResponse>(\n `projects/${config.repository}`,\n );\n if (res.body.archived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n\n if (res.body.marked_for_deletion_at) {\n logger.debug(\n 'Repository is marked for deletion - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_PENDING_DELETION);\n }\n\n if (res.body.mirror && GlobalConfig.get('includeMirrors') !== true) {\n logger.debug(\n 'Repository is a mirror - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (res.body.repository_access_level === 'disabled') {\n logger.debug(\n 'Repository portion of project is disabled - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.merge_requests_access_level === 'disabled') {\n logger.debug(\n 'MRs are disabled for the project - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.default_branch === null || res.body.empty_repo) {\n throw new Error(REPOSITORY_EMPTY);\n }\n config.defaultBranch = res.body.default_branch;\n /* v8 ignore next -- unreachable: null/empty default_branch already threw REPOSITORY_EMPTY above */\n if (!config.defaultBranch) {\n logger.warn({ resBody: res.body }, 'Error fetching GitLab project');\n throw new Error(TEMPORARY_ERROR);\n }\n config.mergeMethod = res.body.merge_method || 'merge';\n config.mergeTrainsEnabled = res.body.merge_trains_enabled ?? false;\n if (res.body.squash_option) {\n config.squash =\n res.body.squash_option === 'always' ||\n res.body.squash_option === 'default_on';\n }\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n logger.debug('Enabling Git FS');\n const url = getRepoUrl(repository, gitUrl, res);\n await git.initRepo({\n ...config,\n url,\n });\n } catch (err) /* v8 ignore next -- initRepo error mapping needs git-level failures not mocked in specs */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (err.message.includes('HEAD is not a symbolic ref')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if (\n [\n REPOSITORY_ARCHIVED,\n REPOSITORY_EMPTY,\n REPOSITORY_PENDING_DELETION,\n ].includes(err.message)\n ) {\n throw err;\n }\n if (err.statusCode === 403) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n logger.debug({ err }, 'Unknown GitLab initRepo error');\n throw err;\n }\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: !!res.body.forked_from_project,\n repoFingerprint: repoFingerprint(res.body.id, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport function getBranchForceRebase(): Promise<boolean> {\n const forceRebase = config?.mergeMethod !== 'merge';\n if (forceRebase) {\n logger.once.debug(\n `mergeMethod is ${config.mergeMethod} so PRs will be kept up-to-date with base branch`,\n );\n }\n return Promise.resolve(forceRebase);\n}\n\n/**\n * Merge trains are GitLab's equivalent of a merge queue. They are enabled per\n * project, so the branch name is not needed.\n * https://docs.gitlab.com/ci/pipelines/merge_trains/\n */\nexport function isBranchMergeQueueEnabled(\n _branchName: string,\n): Promise<boolean> {\n return Promise.resolve(config.mergeTrainsEnabled);\n}\n\n/**\n * GitLab answers with 404 if the MR is not on a merge train. A car that has\n * already been merged is not waiting any more.\n * https://docs.gitlab.com/api/merge_trains/#get-the-status-of-a-merge-request-on-a-merge-train\n */\nexport async function isPrInMergeQueue(id: number): Promise<boolean> {\n if (!config.mergeTrainsEnabled) {\n return false;\n }\n try {\n const { body: status } = await gitlabApi.getJson(\n `projects/${config.repository}/merge_trains/merge_requests/${id}`,\n { memCache: false },\n MergeTrainCarStatus,\n );\n return status !== 'merged';\n } catch (err) {\n if (err.statusCode !== 404) {\n logger.debug({ err }, 'Failed to fetch merge train status');\n }\n return false;\n }\n}\n\ntype BranchState =\n | 'pending'\n | 'created'\n | 'running'\n | 'waiting_for_resource'\n | 'manual'\n | 'success'\n | 'failed'\n | 'canceled'\n | 'skipped'\n | 'scheduled';\n\ninterface GitlabBranchStatus {\n status: BranchState;\n name: string;\n allow_failure?: boolean;\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n sha: string | null = git.getBranchCommit(branchName),\n): Promise<GitlabBranchStatus[]> {\n try {\n // TODO: types (#22198)\n const url = `projects/${\n config.repository\n }/repository/commits/${sha!}/statuses`;\n\n const opts: GitlabHttpOptions = { paginate: true };\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n\n return (await gitlabApi.getJsonUnchecked<GitlabBranchStatus[]>(url, opts))\n .body;\n } catch (err) /* v8 ignore next -- commit status fetch failures map 404 to REPOSITORY_CHANGED, not mocked in specs */ {\n logger.debug({ err }, 'Error getting commit status');\n if (err.response?.statusCode === 404) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nconst gitlabToRenovateStatusMapping: Record<BranchState, BranchStatus> = {\n pending: 'yellow',\n created: 'yellow',\n manual: 'yellow',\n running: 'yellow',\n waiting_for_resource: 'yellow',\n success: 'green',\n failed: 'red',\n canceled: 'red',\n skipped: 'red',\n scheduled: 'yellow',\n};\n\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n\n if (!git.branchExists(branchName)) {\n throw new Error(REPOSITORY_CHANGED);\n }\n\n const branchStatuses = await getStatus(branchName);\n /* v8 ignore next -- defensive: getStatus always resolves to an array in specs */\n if (!isArray(branchStatuses)) {\n logger.warn(\n { branchName, branchStatuses },\n 'Empty or unexpected branch statuses',\n );\n return 'yellow';\n }\n logger.debug(`Got res with ${branchStatuses.length} results`);\n\n const mr = await getBranchPr(branchName);\n if (mr && mr.sha !== mr.headPipelineSha && mr.headPipelineStatus) {\n logger.debug(\n 'Merge request head pipeline has different sha to commit, assuming merged results pipeline',\n );\n branchStatuses.push({\n status: mr.headPipelineStatus as BranchState,\n name: 'head_pipeline',\n });\n }\n // ignore all skipped jobs\n const res = branchStatuses.filter((check) => check.status !== 'skipped');\n if (res.length === 0) {\n // Return 'pending' if we have no status checks\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n branchStatuses.every(\n (check) =>\n check.name?.startsWith('renovate/') &&\n gitlabToRenovateStatusMapping[check.status] === 'green',\n )\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n let status: BranchStatus = 'green'; // default to green\n res\n .filter((check) => !check.allow_failure)\n .forEach((check) => {\n // v8 ignore else -- TODO: add test #40625\n if (status !== 'red') {\n // if red, stay red\n let mappedStatus: BranchStatus =\n gitlabToRenovateStatusMapping[check.status];\n if (!mappedStatus) {\n logger.warn(\n { check },\n 'Could not map GitLab check.status to Renovate status',\n );\n mappedStatus = 'yellow';\n }\n if (mappedStatus !== 'green') {\n logger.trace({ check }, 'Found non-green check');\n status = mappedStatus;\n }\n }\n });\n return status;\n}\n\n// Pull Request\nexport async function getPrList(): Promise<Pr[]> {\n return await GitlabPrCache.getPrs(\n gitlabApi,\n config.repository,\n botUserName,\n !!config.ignorePrAuthor,\n );\n}\n\nasync function ignoreApprovals(pr: number): Promise<void> {\n try {\n const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`;\n const { body: rules } = await gitlabApi.getJsonUnchecked<\n {\n name: string;\n rule_type: string;\n id: number;\n }[]\n >(url);\n\n const ruleName = 'renovateIgnoreApprovals';\n\n const existingAnyApproverRule = rules?.find(\n ({ rule_type }) => rule_type === 'any_approver',\n );\n const existingRegularApproverRules = rules?.filter(\n ({ rule_type, name }) =>\n rule_type !== 'any_approver' &&\n name !== ruleName &&\n rule_type !== 'report_approver' &&\n rule_type !== 'code_owner',\n );\n\n if (existingRegularApproverRules?.length) {\n await p.all(\n existingRegularApproverRules.map((rule) => async (): Promise<void> => {\n await gitlabApi.deleteJson(`${url}/${rule.id}`);\n }),\n );\n }\n\n if (existingAnyApproverRule) {\n await gitlabApi.putJson(`${url}/${existingAnyApproverRule.id}`, {\n body: { ...existingAnyApproverRule, approvals_required: 0 },\n });\n return;\n }\n\n const zeroApproversRule = rules?.find(({ name }) => name === ruleName);\n if (!zeroApproversRule) {\n await gitlabApi.postJson(url, {\n body: {\n name: ruleName,\n approvals_required: 0,\n },\n });\n }\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error adding approval rule');\n }\n}\n\nasync function tryPrAutomerge(\n pr: number,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n try {\n if (platformPrOptions?.gitLabIgnoreApprovals) {\n await ignoreApprovals(pr);\n }\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // https://docs.gitlab.com/ee/api/merge_requests.html#merge-status\n const desiredDetailedMergeStatus = [\n 'mergeable',\n 'ci_still_running',\n 'not_approved',\n ];\n const desiredPipelineStatus = [\n 'failed', // don't lose time if pipeline failed\n 'running', // pipeline is running, no need to wait for it\n ];\n const desiredStatus = 'can_be_merged';\n const env = getEnv();\n // The default value of 5 attempts results in max. 13.75 seconds timeout if no pipeline created.\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS,\n 5,\n );\n\n const mergeDelay = parseInteger(\n env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY,\n 250,\n );\n\n // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n const { body } = await gitlabApi.getJsonUnchecked<{\n merge_status?: string;\n detailed_merge_status?: string;\n merge_when_pipeline_succeeds?: boolean;\n pipeline: {\n status: string;\n };\n }>(`projects/${config.repository}/merge_requests/${pr}`, {\n memCache: false,\n });\n\n // Exit early if merge_when_pipeline_succeeds is already set\n if (body.merge_when_pipeline_succeeds === true) {\n logger.debug(\n 'Skipping automerge retry - merge_when_pipeline_succeeds already enabled',\n );\n return;\n }\n // detailed_merge_status is available with Gitlab >=15.6.0\n const use_detailed_merge_status = !!body.detailed_merge_status;\n const detailed_merge_status_check =\n use_detailed_merge_status &&\n desiredDetailedMergeStatus.includes(body.detailed_merge_status!);\n // merge_status is deprecated with Gitlab >= 15.6\n const deprecated_merge_status_check =\n !use_detailed_merge_status && body.merge_status === desiredStatus;\n\n // Only continue if the merge request can be merged and has a pipeline.\n if (\n (detailed_merge_status_check || deprecated_merge_status_check) &&\n body.pipeline !== null &&\n desiredPipelineStatus.includes(body.pipeline.status)\n ) {\n break;\n }\n logger.debug(`PR not yet in mergeable state. Retrying ${attempt}`);\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n\n // The merge_trains endpoint's auto_merge parameter requires GitLab\n // 17.11+. On older versions we fall back to the /merge endpoint so the\n // MR still automerges, just not on the train.\n // https://docs.gitlab.com/api/merge_trains/#add-a-merge-request-to-a-merge-train\n const useMergeTrain =\n config.mergeTrainsEnabled && !semver.lt(defaults.version, '17.11.0');\n if (config.mergeTrainsEnabled && !useMergeTrain) {\n logger.once.warn(\n { version: defaults.version },\n 'Merge trains require GitLab 17.11.0 or later, falling back to /merge endpoint',\n );\n }\n\n // Even if Gitlab returns a \"merge-able\" merge request status, enabling auto-merge sometimes\n // returns a 405 Method Not Allowed. It seems to be a timing issue within Gitlab.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n try {\n if (useMergeTrain) {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_trains/merge_requests/${pr}`,\n {\n body: {\n auto_merge: true,\n },\n },\n );\n } else {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${pr}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n merge_when_pipeline_succeeds: true,\n },\n },\n );\n }\n break;\n } catch (err) {\n logger.debug(\n { err },\n `Automerge on PR creation failed. Retrying ${attempt}`,\n );\n }\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n }\n } catch (err) /* v8 ignore next -- defensive: retry loop already swallows errors, outer catch is a last resort */ {\n logger.debug({ err }, 'Automerge on PR creation failed');\n }\n}\n\nasync function approveMr(mrNumber: number): Promise<void> {\n const env = getEnv();\n const opts: GitlabHttpOptions = {};\n if (env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN) {\n opts.token = env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN;\n }\n logger.debug(`approveMr(${mrNumber})`);\n try {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${mrNumber}/approve`,\n opts,\n );\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error approving merge request');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawDescription,\n draftPR,\n labels,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n if (draftPR) {\n title = draftPrefix + title;\n }\n const description = sanitize(rawDescription);\n logger.debug(`Creating Merge Request: ${title}`);\n const res = await gitlabApi.postJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests`,\n {\n body: {\n source_branch: sourceBranch,\n target_branch: targetBranch,\n remove_source_branch: true,\n title,\n description,\n labels: coerceArray(labels).join(','),\n squash: config.squash,\n },\n },\n );\n\n const pr = prInfo(res.body);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n pr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(pr.number);\n }\n\n await tryPrAutomerge(pr.number, platformPrOptions);\n\n return pr;\n}\n\nexport async function getPr(iid: number): Promise<GitlabPr> {\n logger.debug(`getPr(${iid})`);\n const mr = await getMR(config.repository, iid);\n\n // Harmonize fields with GitHub\n return prInfo(mr);\n}\n\nexport async function updatePr({\n number: iid,\n prTitle,\n prBody: description,\n addLabels,\n removeLabels,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === iid)?.isDraft) {\n title = draftPrefix + title;\n }\n const newState = {\n ['closed']: 'close',\n ['open']: 'reopen',\n // TODO: null check (#22198)\n }[state!];\n\n const body: any = {\n title,\n description: sanitize(description),\n ...(newState && { state_event: newState }),\n };\n if (targetBranch) {\n body.target_branch = targetBranch;\n }\n\n if (addLabels) {\n body.add_labels = addLabels;\n }\n\n if (removeLabels) {\n body.remove_labels = removeLabels;\n }\n\n const updatedPrInfo = (\n await gitlabApi.putJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests/${iid}`,\n { body },\n )\n ).body;\n\n const updatedPr = prInfo(updatedPrInfo);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n updatedPr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(iid);\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number: iid,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n await tryPrAutomerge(iid, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${iid}`);\n}\n\nasync function tryAddPrToMergeTrain(id: number): Promise<boolean> {\n try {\n // Without `auto_merge` the MR is added to the train immediately. The\n // train merges it and removes the source branch on its own.\n // https://docs.gitlab.com/api/merge_trains/#add-a-merge-request-to-a-merge-train\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_trains/merge_requests/${id}`,\n );\n logger.debug(`MR !${id} added to the merge train`);\n return true;\n } catch (err) {\n logger.debug({ err }, 'Failed to add MR to the merge train');\n return false;\n }\n}\n\nexport async function mergePr({ id }: MergePRConfig): Promise<boolean> {\n if (config.mergeTrainsEnabled) {\n return tryAddPrToMergeTrain(id);\n }\n\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${id}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n },\n },\n );\n return true;\n } catch (err) /* v8 ignore next -- merge rejection statuses (401/406) are mapped to false, not mocked in specs */ {\n if (err.statusCode === 401) {\n logger.debug('No permissions to merge PR');\n return false;\n }\n if (err.statusCode === 406) {\n logger.debug({ err }, 'PR not acceptable for merging');\n return false;\n }\n logger.debug({ err }, 'merge PR error');\n logger.debug('PR merge failed');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n const desc = input\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/\\bPR: #/g), 'MR: !')\n .replace(regEx(/\\bPR\\b/g), 'MR')\n .replace(regEx(/\\bPRs\\b/g), 'MRs')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](#')\n // Strip unicode null characters as GitLab markdown does not permit them\n // oxlint-disable-next-line no-control-regex\n .replace(regEx(/\\u0000/g), '');\n return smartTruncate(desc, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n if (semver.lt(defaults.version, '13.4.0')) {\n logger.debug(\n { version: defaults.version },\n 'GitLab versions earlier than 13.4 have issues with long descriptions, truncating to 25K characters',\n );\n return 25000;\n }\n return 1000000;\n}\n\n/* v8 ignore next: no need to test */\nexport function labelCharLimit(): number {\n return 255;\n}\n\n// Branch\n\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle!}, ${state})`);\n\n if (includeOtherAuthors) {\n // PR might have been created by anyone, so don't use the cached Renovate MR list\n const response = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>(\n `projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`,\n );\n\n const { body: mrList } = response;\n if (!mrList.length) {\n logger.debug(`No MR found for branch ${branchName}`);\n return null;\n }\n\n return prInfo(mrList[0]);\n }\n\n const prList = await getPrList();\n return (\n prList.find(\n (p: { sourceBranch: string; title: string; state: string }) =>\n p.sourceBranch === branchName &&\n (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) &&\n matchesState(p.state, state),\n ) ?? null\n );\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(\n branchName: string,\n): Promise<GitlabPr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\ninterface MergedResultsPipeline {\n id: number;\n sha: string;\n}\n\n// A merged results pipeline runs on the merge ref commit, not on the branch head,\n// so status checks for it have to be set on that commit instead.\nasync function getMergedResultsPipeline(\n branchName: string,\n): Promise<MergedResultsPipeline | null> {\n const branchSha = git.getBranchCommit(branchName);\n const mr = await getBranchPr(branchName);\n if (\n mr?.sha !== branchSha ||\n mr.headPipelineSource !== 'merge_request_event' ||\n !mr.headPipelineId ||\n !mr.headPipelineSha ||\n mr.headPipelineSha === branchSha\n ) {\n return null;\n }\n return { id: mr.headPipelineId, sha: mr.headPipelineSha };\n}\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n // cache-bust in case we have rebased\n let res = await getStatus(branchName, false);\n if (!res.some((check) => check.name === context)) {\n const mergedResultsPipeline = await getMergedResultsPipeline(branchName);\n if (mergedResultsPipeline) {\n res = await getStatus(branchName, false, mergedResultsPipeline.sha);\n }\n }\n logger.debug(`Got res with ${res.length} results`);\n for (const check of res) {\n if (check.name === context) {\n return gitlabToRenovateStatusMapping[check.status] || 'yellow';\n }\n }\n return null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state: renovateState,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n // First, get the branch commit SHA\n const branchSha = git.getBranchCommit(branchName);\n if (!branchSha) {\n logger.warn('Failed to get the branch commit SHA');\n return;\n }\n let statusSha: string = branchSha;\n let state = 'success';\n if (renovateState === 'yellow') {\n state = 'pending';\n } else if (renovateState === 'red') {\n state = 'failed';\n }\n const options: any = {\n state,\n description,\n context,\n };\n\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n\n const env = getEnv();\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_BRANCH_STATUS_CHECK_ATTEMPTS,\n 2,\n );\n\n try {\n for (let attempt = 1; attempt <= retryTimes + 1; attempt += 1) {\n const commitUrl = `projects/${config.repository}/repository/commits/${branchSha}`;\n await gitlabApi\n .getJsonSafe(commitUrl, { memCache: false }, LastPipelineId)\n .onValue((pipelineId) => {\n options.pipeline_id = pipelineId;\n });\n if (options.pipeline_id !== undefined) {\n break;\n }\n if (attempt >= retryTimes + 1) {\n logger.debug(`Pipeline not yet created after ${attempt} attempts`);\n } else {\n logger.debug(`Pipeline not yet created. Retrying ${attempt}`);\n }\n // give gitlab some time to create pipelines for the sha\n await setTimeout(\n parseInteger(env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY, 1000),\n );\n }\n if (options.pipeline_id === undefined) {\n const mergedResultsPipeline = await getMergedResultsPipeline(branchName);\n if (mergedResultsPipeline) {\n logger.debug(\n `Setting branch status on merged results pipeline ${mergedResultsPipeline.id}`,\n );\n options.pipeline_id = mergedResultsPipeline.id;\n statusSha = mergedResultsPipeline.sha;\n }\n }\n } catch (err) {\n logger.debug({ err });\n logger.warn('Failed to retrieve commit pipeline');\n }\n\n if (\n options.pipeline_id === undefined &&\n env.RENOVATE_X_GITLAB_SKIP_STATUS_WITHOUT_PIPELINE === 'true'\n ) {\n logger.debug('Skipping branch status update because no pipeline was found');\n return;\n }\n\n try {\n const url = `projects/${config.repository}/statuses/${statusSha}`;\n await gitlabApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n } catch (err) {\n const message = err.body?.message;\n if (\n isString(message) &&\n message.startsWith('Cannot transition status via :enqueue from :pending')\n ) {\n // https://gitlab.com/gitlab-org/gitlab-foss/issues/25807\n logger.debug('Ignoring status transition error');\n } else {\n logger.debug({ err });\n logger.warn('Failed to set branch status');\n }\n }\n}\n\n// Issue\n\nexport async function getIssueList(): Promise<GitlabIssue[]> {\n // v8 ignore else -- TODO: add test #40625\n if (!config.issueList) {\n const searchParams: Record<string, string> = {\n per_page: '100',\n state: 'opened',\n };\n // v8 ignore else -- TODO: add test #40625\n if (!config.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n const query = getQueryString(searchParams);\n const res = await gitlabApi.getJsonUnchecked<\n { iid: number; title: string; labels: string[] }[]\n >(`projects/${config.repository}/issues?${query}`, {\n memCache: false,\n paginate: true,\n });\n /* v8 ignore next -- defensive: paginated issues endpoint always yields an array in specs */\n if (!isArray(res.body)) {\n logger.warn({ responseBody: res.body }, 'Could not retrieve issue list');\n return [];\n }\n config.issueList = res.body.map((i) => ({\n iid: i.iid,\n title: i.title,\n labels: i.labels,\n }));\n }\n return config.issueList;\n}\n\nexport async function getIssue(\n number: number,\n useCache = true,\n): Promise<Issue | null> {\n try {\n const opts: GitlabHttpOptions = {};\n /* v8 ignore next: temporary code */\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n const issueBody = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${number}`,\n opts,\n )\n ).body.description;\n return {\n number,\n body: issueBody,\n };\n } catch (err) /* v8 ignore next -- defensive: issue fetch failures are logged and swallowed, not simulated in specs */ {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n try {\n const issueList = await getIssueList();\n const issue = issueList.find((i) => i.title === title);\n if (!issue) {\n return null;\n }\n return await getIssue(issue.iid);\n } catch /* v8 ignore next -- defensive: getIssueList/getIssue failures are swallowed, not simulated in specs */ {\n logger.warn('Error finding issue');\n return null;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n labels,\n confidential,\n}: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue()`);\n const description = massageMarkdown(sanitize(body));\n try {\n const issueList = await getIssueList();\n let issue = issueList.find((i) => i.title === title);\n issue ??= issueList.find((i) => i.title === reuseTitle);\n if (issue) {\n const existingDescription = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${issue.iid}`,\n )\n ).body.description;\n if (issue.title !== title || existingDescription !== description) {\n logger.debug('Updating issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: {\n title,\n description,\n labels: coerceArray(labels ?? issue.labels).join(','),\n confidential: confidential ?? false,\n },\n },\n );\n return 'updated';\n }\n } else {\n await gitlabApi.postJson(`projects/${config.repository}/issues`, {\n body: {\n title,\n description,\n labels: coerceArray(labels).join(','),\n confidential: confidential ?? false,\n },\n });\n logger.info('Issue created');\n // delete issueList so that it will be refetched as necessary\n delete config.issueList;\n return 'created';\n }\n } catch (err) /* v8 ignore next -- issue API failures (e.g. issues disabled) are swallowed, not simulated in specs */ {\n if (err.message.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Could not create issue: ${(err as Error).message}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing()`);\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.title === title) {\n logger.debug({ issue }, 'Closing issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: { state_event: 'close' },\n },\n );\n }\n }\n}\n\nexport async function addAssignees(\n iid: number,\n assignees: string[],\n): Promise<void> {\n try {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${iid}`);\n const assigneeIds: number[] = [];\n for (const assignee of assignees) {\n try {\n const userId = await getUserID(assignee);\n assigneeIds.push(userId);\n } catch (err) {\n logger.debug({ assignee, err }, 'getUserID() error');\n logger.warn({ assignee }, 'Failed to add assignee - could not get ID');\n }\n }\n const url = `projects/${\n config.repository\n }/merge_requests/${iid}?${getQueryString({\n 'assignee_ids[]': assigneeIds,\n })}`;\n await gitlabApi.putJson(url);\n } catch (err) {\n logger.debug({ err }, 'addAssignees error');\n logger.warn({ iid, assignees }, 'Failed to add assignees');\n }\n}\n\nexport async function addReviewers(\n iid: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${iid}`);\n\n if (semver.lt(defaults.version, '13.9.0')) {\n logger.warn(\n { version: defaults.version },\n 'Adding reviewers is only available in GitLab 13.9 and onwards',\n );\n return;\n }\n\n let mr: GitLabMergeRequest;\n try {\n mr = await getMR(config.repository, iid);\n } catch (err) {\n logger.warn({ err }, 'Failed to get existing reviewers');\n return;\n }\n\n mr.reviewers = coerceArray(mr.reviewers);\n const existingReviewers = mr.reviewers.map((r) => r.username);\n const existingReviewerIDs = mr.reviewers.map((r) => r.id);\n\n // Figure out which reviewers (of the ones we want to add) are not already on the MR as a reviewer\n const newReviewers = reviewers.filter((r) => !existingReviewers.includes(r));\n\n // Gather the IDs for all the reviewers we want to add\n let newReviewerIDs: number[];\n newReviewerIDs = (\n await p.all(\n newReviewers.map((r) => async () => {\n try {\n return [await getUserID(r)];\n } catch {\n // Unable to fetch userId, try resolve as a group\n return getMemberUserIDs(r);\n }\n }),\n )\n ).flat();\n\n if (isNonEmptyArray(newReviewers) && isEmptyArray(newReviewerIDs)) {\n logger.warn('Failed to get IDs of the new reviewers');\n return;\n }\n\n // Multiple groups may have the same members, so\n // filter out non-distinct values\n newReviewerIDs = [...new Set(newReviewerIDs)];\n\n try {\n await updateMR(config.repository, iid, {\n reviewer_ids: [...existingReviewerIDs, ...newReviewerIDs],\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to add reviewers');\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n try {\n const pr = await getPr(issueNo);\n const labels = coerceArray(pr.labels)\n .filter((l: string) => l !== label)\n .join(',');\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}`,\n {\n body: { labels },\n },\n );\n } catch (err) /* v8 ignore next -- defensive: label deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function getComments(issueNo: number): Promise<GitlabComment[]> {\n // GET projects/:owner/:repo/merge_requests/:number/notes\n logger.debug(`Getting comments for #${issueNo}`);\n const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`;\n const comments = (\n await gitlabApi.getJsonUnchecked<GitlabComment[]>(url, { paginate: true })\n ).body;\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST projects/:owner/:repo/merge_requests/:number/notes\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(\n issueNo: number,\n commentId: number,\n body: string,\n): Promise<void> {\n // PUT projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(\n issueNo: number,\n commentId: number,\n): Promise<void> {\n // DELETE projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.deleteJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n );\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n const massagedTopic = topic\n ? topic\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR')\n : topic;\n const comments = await getComments(number);\n let body: string;\n let commentId: number | undefined;\n let commentNeedsUpdating: boolean | undefined;\n // TODO: types (#22198)\n if (topic) {\n logger.debug(`Ensuring comment \"${massagedTopic!}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n body = smartTruncate(\n body\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR'),\n maxBodyLength(),\n );\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body.startsWith(`### ${massagedTopic!}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = smartTruncate(`${sanitizedContent}`, maxBodyLength());\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Added comment',\n );\n } else if (commentNeedsUpdating) {\n await editComment(number, commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Updated comment',\n );\n } else {\n logger.debug('Comment is already up-to-date');\n }\n return true;\n}\n\nfunction byTopic(comment: GitlabComment, topic: string): boolean {\n return comment.body.startsWith(`### ${topic}\\n\\n`);\n}\n\nfunction byContent(comment: GitlabComment, content: string): boolean {\n return comment.body.trim() === content;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const topic = deleteConfig.topic;\n commentId = comments.find((comment) => byTopic(comment, topic))?.id;\n } else if (deleteConfig.type === 'by-content') {\n const content = deleteConfig.content;\n commentId = comments.find((comment) => byContent(comment, content))?.id;\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n await deleteComment(issueNo, commentId);\n }\n}\n\nexport async function filterUnavailableUsers(\n users: string[],\n): Promise<string[]> {\n const filteredUsers: string[] = [];\n for (const user of users) {\n if (!(await isUserBusy(user))) {\n filteredUsers.push(user);\n }\n }\n return filteredUsers;\n}\n\nexport async function expandGroupMembers(\n reviewersOrAssignees: string[],\n): Promise<string[]> {\n const expandedReviewersOrAssignees: string[] = [];\n const normalizedReviewersOrAssigneesWithoutEmails: string[] = [];\n\n // Skip passing user emails to Gitlab API, but include them in the final result\n for (const reviewerOrAssignee of reviewersOrAssignees) {\n // Resolve GitLab CODEOWNERS role handles (@@developer, @@maintainer,\n // @@owner) to project members instead of treating them as groups\n const roleAccessLevel = getRoleAccessLevel(reviewerOrAssignee);\n if (roleAccessLevel !== null) {\n try {\n const members = await getProjectMembersByRole(\n config.repository,\n roleAccessLevel,\n );\n expandedReviewersOrAssignees.push(...members.map((u) => u.username));\n } catch (err) {\n logger.debug(\n { err, reviewerOrAssignee },\n 'Unable to fetch role members',\n );\n }\n continue;\n }\n\n if (reviewerOrAssignee.indexOf('@') > 0) {\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n continue;\n }\n\n // Normalize the potential group names before passing to Gitlab API\n normalizedReviewersOrAssigneesWithoutEmails.push(\n noLeadingAtSymbol(reviewerOrAssignee),\n );\n }\n\n for (const reviewerOrAssignee of normalizedReviewersOrAssigneesWithoutEmails) {\n try {\n const members = await getMemberUsernames(reviewerOrAssignee);\n expandedReviewersOrAssignees.push(...members);\n } catch (err) {\n if (err.statusCode !== 404) {\n logger.debug({ err, reviewerOrAssignee }, 'Unable to fetch group');\n }\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n }\n }\n return expandedReviewersOrAssignees;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["git.initRepo","git.getBranchCommit","git.branchExists","p.all"],"sources":["../../../../lib/modules/platform/gitlab/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport {\n isArray,\n isEmptyArray,\n isNonEmptyArray,\n isString,\n} from '@sindresorhus/is';\nimport pMap from 'p-map';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n REPOSITORY_NOT_FOUND,\n REPOSITORY_PENDING_DELETION,\n TEMPORARY_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { noLeadingAtSymbol, parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { GitlabHttpOptions } from '../../../util/http/gitlab.ts';\nimport { setBaseUrl } from '../../../util/http/gitlab.ts';\nimport {\n isForbidden,\n isNotAcceptable,\n isNotFound,\n isUnauthorized,\n} from '../../../util/http/status.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { parseInteger } from '../../../util/number.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { EmailAddress } from '../../../util/schema-utils/index.ts';\nimport {\n ensureTrailingSlash,\n getQueryString,\n parseUrl,\n} from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { getRepoFile } from './files.ts';\nimport {\n getMemberUserIDs,\n getMemberUsernames,\n getProjectMembersByRole,\n getUserID,\n gitlabApi,\n isUserBusy,\n} from './http.ts';\nimport { getMR, updateMR } from './merge-request.ts';\nimport { GitlabPrCache } from './pr-cache.ts';\nimport { getRoleAccessLevel } from './roles.ts';\nimport type { GitLabMergeRequest } from './schema.ts';\nimport { LastPipelineId, MergeTrainCarStatus } from './schema.ts';\nimport type {\n GitlabComment,\n GitlabIssue,\n GitlabPr,\n MergeMethod,\n RepoResponse,\n} from './types.ts';\nimport {\n DRAFT_PREFIX,\n DRAFT_PREFIX_DEPRECATED,\n defaults,\n getRepoUrl,\n prInfo,\n} from './utils.ts';\n\nexport { extractRulesFromCodeOwnersLines } from './code-owners.ts';\n\nlet config: {\n repository: string;\n email: EmailAddress;\n issueList: GitlabIssue[] | undefined;\n mergeMethod: MergeMethod;\n mergeTrainsEnabled: boolean;\n defaultBranch: string;\n cloneSubmodules: boolean | undefined;\n cloneSubmodulesFilter: string[] | undefined;\n ignorePrAuthor: boolean | undefined;\n squash: boolean;\n} = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n draftPrefix = DRAFT_PREFIX;\n defaults.hostType = 'gitlab';\n defaults.endpoint = 'https://gitlab.com/api/v4/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nexport const id = 'gitlab';\n\nlet draftPrefix = DRAFT_PREFIX;\nlet botUserName: string;\n\nexport async function initPlatform({\n endpoint,\n username,\n token,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error('Init: You must configure a GitLab personal access token');\n }\n if (!endpoint) {\n logger.debug(`Using default GitLab endpoint: ${defaults.endpoint}`);\n } else if (parseUrl(endpoint) === null) {\n throw new Error(`Invalid GitLab endpoint URL: ${endpoint}`);\n } else {\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n }\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n let gitlabVersion: string;\n try {\n if (!gitAuthor) {\n const user = (\n await gitlabApi.getJsonUnchecked<{\n email: EmailAddress;\n name: string;\n id: number;\n commit_email?: EmailAddress;\n }>(`user`, { token })\n ).body;\n platformConfig.gitAuthor = `${user.name} <${\n user.commit_email ?? user.email\n }>`;\n botUserName = user.name;\n }\n const env = getEnv();\n /* v8 ignore next: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gitlabVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n const version = (\n await gitlabApi.getJsonUnchecked<{ version: string }>('version', {\n token,\n })\n ).body;\n gitlabVersion = version.version;\n }\n logger.debug(`GitLab version is: ${gitlabVersion}`);\n // version is 'x.y.z-edition', so not strictly semver; need to strip edition\n [gitlabVersion] = gitlabVersion.split('-');\n defaults.version = gitlabVersion;\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with GitLab. Check that your token includes \"api\" permissions',\n );\n throw new Error('Init: Authentication failure');\n }\n draftPrefix = semver.lt(defaults.version, '13.2.0')\n ? DRAFT_PREFIX_DEPRECATED\n : DRAFT_PREFIX;\n\n botUserName ??= username!;\n\n return platformConfig;\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering GitLab repositories');\n\n const queryParams: Record<string, any> = {\n membership: true,\n per_page: 100,\n with_merge_requests_enabled: true,\n min_access_level: 30,\n archived: false,\n ...(config?.sort && { order_by: config.sort }),\n ...(config?.order && { sort: config.order }),\n };\n if (config?.topics?.length) {\n queryParams.topic = config.topics.join(',');\n }\n\n const urls = [];\n if (config?.namespaces?.length) {\n queryParams.with_shared = false;\n queryParams.include_subgroups = true;\n urls.push(\n ...config.namespaces.map(\n (namespace) =>\n `groups/${urlEscape(namespace)}/projects?${getQueryString(\n queryParams,\n )}`,\n ),\n );\n } else {\n urls.push(`projects?${getQueryString(queryParams)}`);\n }\n\n try {\n const repos = (\n await pMap(\n urls,\n (url) =>\n gitlabApi.getJsonUnchecked<RepoResponse[]>(url, {\n paginate: true,\n }),\n {\n concurrency: 2,\n },\n )\n ).flatMap((response) => response.body);\n\n logger.debug(`Discovered ${repos.length} project(s)`);\n return repos\n .filter((repo) => !repo.mirror || config?.includeMirrors)\n .filter((repo) => !repo.marked_for_deletion_at)\n .map((repo) => repo.path_with_namespace);\n } catch (err) {\n logger.error({ err }, `GitLab getRepos error`);\n throw err;\n }\n}\n\nfunction urlEscape(str: string): string;\nfunction urlEscape(str: string | undefined): string | undefined;\nfunction urlEscape(str: string | undefined): string | undefined {\n return str?.replace(regEx(/\\//g), '%2F');\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = urlEscape(repoName) ?? config.repository;\n return await getRepoFile(gitlabApi, repo, fileName, branchOrTag, {\n cacheProvider: memCacheProvider,\n });\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize GitLab by getting base branch\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n config = {} as any;\n config.repository = urlEscape(repository);\n config.cloneSubmodules = cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n let res: HttpResponse<RepoResponse>;\n try {\n res = await gitlabApi.getJsonUnchecked<RepoResponse>(\n `projects/${config.repository}`,\n );\n if (res.body.archived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n\n if (res.body.marked_for_deletion_at) {\n logger.debug(\n 'Repository is marked for deletion - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_PENDING_DELETION);\n }\n\n if (res.body.mirror && GlobalConfig.get('includeMirrors') !== true) {\n logger.debug(\n 'Repository is a mirror - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (res.body.repository_access_level === 'disabled') {\n logger.debug(\n 'Repository portion of project is disabled - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.merge_requests_access_level === 'disabled') {\n logger.debug(\n 'MRs are disabled for the project - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.default_branch === null || res.body.empty_repo) {\n throw new Error(REPOSITORY_EMPTY);\n }\n config.defaultBranch = res.body.default_branch;\n /* v8 ignore next -- unreachable: null/empty default_branch already threw REPOSITORY_EMPTY above */\n if (!config.defaultBranch) {\n logger.warn({ resBody: res.body }, 'Error fetching GitLab project');\n throw new Error(TEMPORARY_ERROR);\n }\n config.mergeMethod = res.body.merge_method || 'merge';\n config.mergeTrainsEnabled = res.body.merge_trains_enabled ?? false;\n if (res.body.squash_option) {\n config.squash =\n res.body.squash_option === 'always' ||\n res.body.squash_option === 'default_on';\n }\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n logger.debug('Enabling Git FS');\n const url = getRepoUrl(repository, gitUrl, res);\n await git.initRepo({\n ...config,\n url,\n });\n } catch (err) /* v8 ignore next -- initRepo error mapping needs git-level failures not mocked in specs */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (err.message.includes('HEAD is not a symbolic ref')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if (\n [\n REPOSITORY_ARCHIVED,\n REPOSITORY_EMPTY,\n REPOSITORY_PENDING_DELETION,\n ].includes(err.message)\n ) {\n throw err;\n }\n if (isForbidden(err)) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (isNotFound(err)) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n logger.debug({ err }, 'Unknown GitLab initRepo error');\n throw err;\n }\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: !!res.body.forked_from_project,\n repoFingerprint: repoFingerprint(res.body.id, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport function getBranchForceRebase(): Promise<boolean> {\n const forceRebase = config?.mergeMethod !== 'merge';\n if (forceRebase) {\n logger.once.debug(\n `mergeMethod is ${config.mergeMethod} so PRs will be kept up-to-date with base branch`,\n );\n }\n return Promise.resolve(forceRebase);\n}\n\n/**\n * Merge trains are GitLab's equivalent of a merge queue. They are enabled per\n * project, so the branch name is not needed.\n * https://docs.gitlab.com/ci/pipelines/merge_trains/\n */\nexport function isBranchMergeQueueEnabled(\n _branchName: string,\n): Promise<boolean> {\n return Promise.resolve(config.mergeTrainsEnabled);\n}\n\n/**\n * GitLab answers with 404 if the MR is not on a merge train. A car that has\n * already been merged is not waiting any more.\n * https://docs.gitlab.com/api/merge_trains/#get-the-status-of-a-merge-request-on-a-merge-train\n */\nexport async function isPrInMergeQueue(id: number): Promise<boolean> {\n if (!config.mergeTrainsEnabled) {\n return false;\n }\n try {\n const { body: status } = await gitlabApi.getJson(\n `projects/${config.repository}/merge_trains/merge_requests/${id}`,\n { memCache: false },\n MergeTrainCarStatus,\n );\n return status !== 'merged';\n } catch (err) {\n if (!isNotFound(err)) {\n logger.debug({ err }, 'Failed to fetch merge train status');\n }\n return false;\n }\n}\n\ntype BranchState =\n | 'pending'\n | 'created'\n | 'running'\n | 'waiting_for_resource'\n | 'manual'\n | 'success'\n | 'failed'\n | 'canceled'\n | 'skipped'\n | 'scheduled';\n\ninterface GitlabBranchStatus {\n status: BranchState;\n name: string;\n allow_failure?: boolean;\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n sha: string | null = git.getBranchCommit(branchName),\n): Promise<GitlabBranchStatus[]> {\n try {\n // TODO: types (#22198)\n const url = `projects/${\n config.repository\n }/repository/commits/${sha!}/statuses`;\n\n const opts: GitlabHttpOptions = { paginate: true };\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n\n return (await gitlabApi.getJsonUnchecked<GitlabBranchStatus[]>(url, opts))\n .body;\n } catch (err) /* v8 ignore next -- commit status fetch failures map 404 to REPOSITORY_CHANGED, not mocked in specs */ {\n logger.debug({ err }, 'Error getting commit status');\n if (isNotFound(err)) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nconst gitlabToRenovateStatusMapping: Record<BranchState, BranchStatus> = {\n pending: 'yellow',\n created: 'yellow',\n manual: 'yellow',\n running: 'yellow',\n waiting_for_resource: 'yellow',\n success: 'green',\n failed: 'red',\n canceled: 'red',\n skipped: 'red',\n scheduled: 'yellow',\n};\n\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n\n if (!git.branchExists(branchName)) {\n throw new Error(REPOSITORY_CHANGED);\n }\n\n const branchStatuses = await getStatus(branchName);\n /* v8 ignore next -- defensive: getStatus always resolves to an array in specs */\n if (!isArray(branchStatuses)) {\n logger.warn(\n { branchName, branchStatuses },\n 'Empty or unexpected branch statuses',\n );\n return 'yellow';\n }\n logger.debug(`Got res with ${branchStatuses.length} results`);\n\n const mr = await getBranchPr(branchName);\n if (mr && mr.sha !== mr.headPipelineSha && mr.headPipelineStatus) {\n logger.debug(\n 'Merge request head pipeline has different sha to commit, assuming merged results pipeline',\n );\n branchStatuses.push({\n status: mr.headPipelineStatus as BranchState,\n name: 'head_pipeline',\n });\n }\n // ignore all skipped jobs\n const res = branchStatuses.filter((check) => check.status !== 'skipped');\n if (res.length === 0) {\n // Return 'pending' if we have no status checks\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n branchStatuses.every((check) => {\n const isGreen = gitlabToRenovateStatusMapping[check.status] === 'green';\n return check.name?.startsWith('renovate/') && isGreen;\n })\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n let status: BranchStatus = 'green'; // default to green\n res\n .filter((check) => !check.allow_failure)\n .forEach((check) => {\n // v8 ignore else -- TODO: add test #40625\n if (status !== 'red') {\n // if red, stay red\n let mappedStatus: BranchStatus =\n gitlabToRenovateStatusMapping[check.status];\n if (!mappedStatus) {\n logger.warn(\n { check },\n 'Could not map GitLab check.status to Renovate status',\n );\n mappedStatus = 'yellow';\n }\n if (mappedStatus !== 'green') {\n logger.trace({ check }, 'Found non-green check');\n status = mappedStatus;\n }\n }\n });\n return status;\n}\n\n// Pull Request\nexport async function getPrList(): Promise<Pr[]> {\n return await GitlabPrCache.getPrs(\n gitlabApi,\n config.repository,\n botUserName,\n !!config.ignorePrAuthor,\n );\n}\n\nasync function ignoreApprovals(pr: number): Promise<void> {\n try {\n const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`;\n const { body: rules } = await gitlabApi.getJsonUnchecked<\n {\n name: string;\n rule_type: string;\n id: number;\n }[]\n >(url);\n\n const ruleName = 'renovateIgnoreApprovals';\n\n const existingAnyApproverRule = rules?.find(\n ({ rule_type }) => rule_type === 'any_approver',\n );\n const existingRegularApproverRules = rules?.filter(\n ({ rule_type, name }) =>\n rule_type !== 'any_approver' &&\n name !== ruleName &&\n rule_type !== 'report_approver' &&\n rule_type !== 'code_owner',\n );\n\n if (existingRegularApproverRules?.length) {\n await p.all(\n existingRegularApproverRules.map((rule) => async (): Promise<void> => {\n await gitlabApi.deleteJson(`${url}/${rule.id}`);\n }),\n );\n }\n\n if (existingAnyApproverRule) {\n await gitlabApi.putJson(`${url}/${existingAnyApproverRule.id}`, {\n body: { ...existingAnyApproverRule, approvals_required: 0 },\n });\n return;\n }\n\n const zeroApproversRule = rules?.find(({ name }) => name === ruleName);\n if (!zeroApproversRule) {\n await gitlabApi.postJson(url, {\n body: {\n name: ruleName,\n approvals_required: 0,\n },\n });\n }\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error adding approval rule');\n }\n}\n\nasync function tryPrAutomerge(\n pr: number,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n try {\n if (platformPrOptions?.gitLabIgnoreApprovals) {\n await ignoreApprovals(pr);\n }\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // https://docs.gitlab.com/ee/api/merge_requests.html#merge-status\n const desiredDetailedMergeStatus = [\n 'mergeable',\n 'ci_still_running',\n 'not_approved',\n ];\n const desiredPipelineStatus = [\n 'failed', // don't lose time if pipeline failed\n 'running', // pipeline is running, no need to wait for it\n ];\n const desiredStatus = 'can_be_merged';\n const env = getEnv();\n // The default value of 5 attempts results in max. 13.75 seconds timeout if no pipeline created.\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS,\n 5,\n );\n\n const mergeDelay = parseInteger(\n env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY,\n 250,\n );\n\n // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n const { body } = await gitlabApi.getJsonUnchecked<{\n merge_status?: string;\n detailed_merge_status?: string;\n merge_when_pipeline_succeeds?: boolean;\n pipeline: {\n status: string;\n };\n }>(`projects/${config.repository}/merge_requests/${pr}`, {\n memCache: false,\n });\n\n // Exit early if merge_when_pipeline_succeeds is already set\n if (body.merge_when_pipeline_succeeds === true) {\n logger.debug(\n 'Skipping automerge retry - merge_when_pipeline_succeeds already enabled',\n );\n return;\n }\n // detailed_merge_status is available with Gitlab >=15.6.0\n const use_detailed_merge_status = !!body.detailed_merge_status;\n const detailed_merge_status_check =\n use_detailed_merge_status &&\n desiredDetailedMergeStatus.includes(body.detailed_merge_status!);\n // merge_status is deprecated with Gitlab >= 15.6\n const deprecated_merge_status_check =\n !use_detailed_merge_status && body.merge_status === desiredStatus;\n\n // Only continue if the merge request can be merged and has a pipeline.\n const merge_status_check =\n detailed_merge_status_check || deprecated_merge_status_check;\n if (\n merge_status_check &&\n body.pipeline !== null &&\n desiredPipelineStatus.includes(body.pipeline.status)\n ) {\n break;\n }\n logger.debug(`PR not yet in mergeable state. Retrying ${attempt}`);\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n\n // The merge_trains endpoint's auto_merge parameter requires GitLab\n // 17.11+. On older versions we fall back to the /merge endpoint so the\n // MR still automerges, just not on the train.\n // https://docs.gitlab.com/api/merge_trains/#add-a-merge-request-to-a-merge-train\n const useMergeTrain =\n config.mergeTrainsEnabled && !semver.lt(defaults.version, '17.11.0');\n if (config.mergeTrainsEnabled && !useMergeTrain) {\n logger.once.warn(\n { version: defaults.version },\n 'Merge trains require GitLab 17.11.0 or later, falling back to /merge endpoint',\n );\n }\n\n // Even if Gitlab returns a \"merge-able\" merge request status, enabling auto-merge sometimes\n // returns a 405 Method Not Allowed. It seems to be a timing issue within Gitlab.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n try {\n if (useMergeTrain) {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_trains/merge_requests/${pr}`,\n {\n body: {\n auto_merge: true,\n },\n },\n );\n } else {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${pr}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n merge_when_pipeline_succeeds: true,\n },\n },\n );\n }\n break;\n } catch (err) {\n logger.debug(\n { err },\n `Automerge on PR creation failed. Retrying ${attempt}`,\n );\n }\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n }\n } catch (err) /* v8 ignore next -- defensive: retry loop already swallows errors, outer catch is a last resort */ {\n logger.debug({ err }, 'Automerge on PR creation failed');\n }\n}\n\nasync function approveMr(mrNumber: number): Promise<void> {\n const env = getEnv();\n const opts: GitlabHttpOptions = {};\n if (env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN) {\n opts.token = env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN;\n }\n logger.debug(`approveMr(${mrNumber})`);\n try {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${mrNumber}/approve`,\n opts,\n );\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error approving merge request');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawDescription,\n draftPR,\n labels,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n if (draftPR) {\n title = draftPrefix + title;\n }\n const description = sanitize(rawDescription);\n logger.debug(`Creating Merge Request: ${title}`);\n const res = await gitlabApi.postJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests`,\n {\n body: {\n source_branch: sourceBranch,\n target_branch: targetBranch,\n remove_source_branch: true,\n title,\n description,\n labels: coerceArray(labels).join(','),\n squash: config.squash,\n },\n },\n );\n\n const pr = prInfo(res.body);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n pr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(pr.number);\n }\n\n await tryPrAutomerge(pr.number, platformPrOptions);\n\n return pr;\n}\n\nexport async function getPr(iid: number): Promise<GitlabPr> {\n logger.debug(`getPr(${iid})`);\n const mr = await getMR(config.repository, iid);\n\n // Harmonize fields with GitHub\n return prInfo(mr);\n}\n\nexport async function updatePr({\n number: iid,\n prTitle,\n prBody: description,\n addLabels,\n removeLabels,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === iid)?.isDraft) {\n title = draftPrefix + title;\n }\n const newState = {\n ['closed']: 'close',\n ['open']: 'reopen',\n // TODO: null check (#22198)\n }[state!];\n\n const body: any = {\n title,\n description: sanitize(description),\n ...(newState && { state_event: newState }),\n };\n if (targetBranch) {\n body.target_branch = targetBranch;\n }\n\n if (addLabels) {\n body.add_labels = addLabels;\n }\n\n if (removeLabels) {\n body.remove_labels = removeLabels;\n }\n\n const updatedPrInfo = (\n await gitlabApi.putJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests/${iid}`,\n { body },\n )\n ).body;\n\n const updatedPr = prInfo(updatedPrInfo);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n updatedPr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(iid);\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number: iid,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n await tryPrAutomerge(iid, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${iid}`);\n}\n\nasync function tryAddPrToMergeTrain(id: number): Promise<boolean> {\n try {\n // Without `auto_merge` the MR is added to the train immediately. The\n // train merges it and removes the source branch on its own.\n // https://docs.gitlab.com/api/merge_trains/#add-a-merge-request-to-a-merge-train\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_trains/merge_requests/${id}`,\n );\n logger.debug(`MR !${id} added to the merge train`);\n return true;\n } catch (err) {\n logger.debug({ err }, 'Failed to add MR to the merge train');\n return false;\n }\n}\n\nexport async function mergePr({ id }: MergePRConfig): Promise<boolean> {\n if (config.mergeTrainsEnabled) {\n return tryAddPrToMergeTrain(id);\n }\n\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${id}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n },\n },\n );\n return true;\n } catch (err) /* v8 ignore next -- merge rejection statuses (401/406) are mapped to false, not mocked in specs */ {\n if (isUnauthorized(err)) {\n logger.debug('No permissions to merge PR');\n return false;\n }\n if (isNotAcceptable(err)) {\n logger.debug({ err }, 'PR not acceptable for merging');\n return false;\n }\n logger.debug({ err }, 'merge PR error');\n logger.debug('PR merge failed');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n const desc = input\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/\\bPR: #/g), 'MR: !')\n .replace(regEx(/\\bPR\\b/g), 'MR')\n .replace(regEx(/\\bPRs\\b/g), 'MRs')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](#')\n // Strip unicode null characters as GitLab markdown does not permit them\n // oxlint-disable-next-line no-control-regex\n .replace(regEx(/\\u0000/g), '');\n return smartTruncate(desc, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n if (semver.lt(defaults.version, '13.4.0')) {\n logger.debug(\n { version: defaults.version },\n 'GitLab versions earlier than 13.4 have issues with long descriptions, truncating to 25K characters',\n );\n return 25000;\n }\n return 1000000;\n}\n\n/* v8 ignore next: no need to test */\nexport function labelCharLimit(): number {\n return 255;\n}\n\n// Branch\n\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle!}, ${state})`);\n\n if (includeOtherAuthors) {\n // PR might have been created by anyone, so don't use the cached Renovate MR list\n const response = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>(\n `projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`,\n );\n\n const { body: mrList } = response;\n if (!mrList.length) {\n logger.debug(`No MR found for branch ${branchName}`);\n return null;\n }\n\n return prInfo(mrList[0]);\n }\n\n const prList = await getPrList();\n const pr = prList.find(\n (p: { sourceBranch: string; title: string; state: string }) => {\n if (p.sourceBranch !== branchName || !matchesState(p.state, state)) {\n return false;\n }\n return !prTitle || p.title.toUpperCase() === prTitle.toUpperCase();\n },\n );\n return pr ?? null;\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(\n branchName: string,\n): Promise<GitlabPr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\ninterface MergedResultsPipeline {\n id: number;\n sha: string;\n}\n\n// A merged results pipeline runs on the merge ref commit, not on the branch head,\n// so status checks for it have to be set on that commit instead.\nasync function getMergedResultsPipeline(\n branchName: string,\n): Promise<MergedResultsPipeline | null> {\n const branchSha = git.getBranchCommit(branchName);\n const mr = await getBranchPr(branchName);\n if (\n mr?.sha !== branchSha ||\n mr.headPipelineSource !== 'merge_request_event' ||\n !mr.headPipelineId ||\n !mr.headPipelineSha ||\n mr.headPipelineSha === branchSha\n ) {\n return null;\n }\n return { id: mr.headPipelineId, sha: mr.headPipelineSha };\n}\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n // cache-bust in case we have rebased\n let res = await getStatus(branchName, false);\n if (!res.some((check) => check.name === context)) {\n const mergedResultsPipeline = await getMergedResultsPipeline(branchName);\n if (mergedResultsPipeline) {\n res = await getStatus(branchName, false, mergedResultsPipeline.sha);\n }\n }\n logger.debug(`Got res with ${res.length} results`);\n for (const check of res) {\n if (check.name === context) {\n return gitlabToRenovateStatusMapping[check.status] || 'yellow';\n }\n }\n return null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state: renovateState,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n // First, get the branch commit SHA\n const branchSha = git.getBranchCommit(branchName);\n if (!branchSha) {\n logger.warn('Failed to get the branch commit SHA');\n return;\n }\n let statusSha: string = branchSha;\n let state = 'success';\n if (renovateState === 'yellow') {\n state = 'pending';\n } else if (renovateState === 'red') {\n state = 'failed';\n }\n const options: any = {\n state,\n description,\n context,\n };\n\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n\n const env = getEnv();\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_BRANCH_STATUS_CHECK_ATTEMPTS,\n 2,\n );\n\n try {\n for (let attempt = 1; attempt <= retryTimes + 1; attempt += 1) {\n const commitUrl = `projects/${config.repository}/repository/commits/${branchSha}`;\n await gitlabApi\n .getJsonSafe(commitUrl, { memCache: false }, LastPipelineId)\n .onValue((pipelineId) => {\n options.pipeline_id = pipelineId;\n });\n if (options.pipeline_id !== undefined) {\n break;\n }\n if (attempt >= retryTimes + 1) {\n logger.debug(`Pipeline not yet created after ${attempt} attempts`);\n } else {\n logger.debug(`Pipeline not yet created. Retrying ${attempt}`);\n }\n // give gitlab some time to create pipelines for the sha\n await setTimeout(\n parseInteger(env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY, 1000),\n );\n }\n if (options.pipeline_id === undefined) {\n const mergedResultsPipeline = await getMergedResultsPipeline(branchName);\n if (mergedResultsPipeline) {\n logger.debug(\n `Setting branch status on merged results pipeline ${mergedResultsPipeline.id}`,\n );\n options.pipeline_id = mergedResultsPipeline.id;\n statusSha = mergedResultsPipeline.sha;\n }\n }\n } catch (err) {\n logger.debug({ err });\n logger.warn('Failed to retrieve commit pipeline');\n }\n\n if (\n options.pipeline_id === undefined &&\n env.RENOVATE_X_GITLAB_SKIP_STATUS_WITHOUT_PIPELINE === 'true'\n ) {\n logger.debug('Skipping branch status update because no pipeline was found');\n return;\n }\n\n try {\n const url = `projects/${config.repository}/statuses/${statusSha}`;\n await gitlabApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n } catch (err) {\n const message = err.body?.message;\n if (\n isString(message) &&\n message.startsWith('Cannot transition status via :enqueue from :pending')\n ) {\n // https://gitlab.com/gitlab-org/gitlab-foss/issues/25807\n logger.debug('Ignoring status transition error');\n } else {\n logger.debug({ err });\n logger.warn('Failed to set branch status');\n }\n }\n}\n\n// Issue\n\nexport async function getIssueList(): Promise<GitlabIssue[]> {\n // v8 ignore else -- TODO: add test #40625\n if (!config.issueList) {\n const searchParams: Record<string, string> = {\n per_page: '100',\n state: 'opened',\n };\n // v8 ignore else -- TODO: add test #40625\n if (!config.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n const query = getQueryString(searchParams);\n const res = await gitlabApi.getJsonUnchecked<\n { iid: number; title: string; labels: string[] }[]\n >(`projects/${config.repository}/issues?${query}`, {\n memCache: false,\n paginate: true,\n });\n /* v8 ignore next -- defensive: paginated issues endpoint always yields an array in specs */\n if (!isArray(res.body)) {\n logger.warn({ responseBody: res.body }, 'Could not retrieve issue list');\n return [];\n }\n config.issueList = res.body.map((i) => ({\n iid: i.iid,\n title: i.title,\n labels: i.labels,\n }));\n }\n return config.issueList;\n}\n\nexport async function getIssue(\n number: number,\n useCache = true,\n): Promise<Issue | null> {\n try {\n const opts: GitlabHttpOptions = {};\n /* v8 ignore next: temporary code */\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n const issueBody = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${number}`,\n opts,\n )\n ).body.description;\n return {\n number,\n body: issueBody,\n };\n } catch (err) /* v8 ignore next -- defensive: issue fetch failures are logged and swallowed, not simulated in specs */ {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n try {\n const issueList = await getIssueList();\n const issue = issueList.find((i) => i.title === title);\n if (!issue) {\n return null;\n }\n return await getIssue(issue.iid);\n } catch /* v8 ignore next -- defensive: getIssueList/getIssue failures are swallowed, not simulated in specs */ {\n logger.warn('Error finding issue');\n return null;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n labels,\n confidential,\n}: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue()`);\n const description = massageMarkdown(sanitize(body));\n try {\n const issueList = await getIssueList();\n let issue = issueList.find((i) => i.title === title);\n issue ??= issueList.find((i) => i.title === reuseTitle);\n if (issue) {\n const existingDescription = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${issue.iid}`,\n )\n ).body.description;\n if (issue.title !== title || existingDescription !== description) {\n logger.debug('Updating issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: {\n title,\n description,\n labels: coerceArray(labels ?? issue.labels).join(','),\n confidential: confidential ?? false,\n },\n },\n );\n return 'updated';\n }\n } else {\n await gitlabApi.postJson(`projects/${config.repository}/issues`, {\n body: {\n title,\n description,\n labels: coerceArray(labels).join(','),\n confidential: confidential ?? false,\n },\n });\n logger.info('Issue created');\n // delete issueList so that it will be refetched as necessary\n delete config.issueList;\n return 'created';\n }\n } catch (err) /* v8 ignore next -- issue API failures (e.g. issues disabled) are swallowed, not simulated in specs */ {\n if (err.message.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Could not create issue: ${(err as Error).message}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing()`);\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.title === title) {\n logger.debug({ issue }, 'Closing issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: { state_event: 'close' },\n },\n );\n }\n }\n}\n\nexport async function addAssignees(\n iid: number,\n assignees: string[],\n): Promise<void> {\n try {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${iid}`);\n const assigneeIds: number[] = [];\n for (const assignee of assignees) {\n try {\n const userId = await getUserID(assignee);\n assigneeIds.push(userId);\n } catch (err) {\n logger.debug({ assignee, err }, 'getUserID() error');\n logger.warn({ assignee }, 'Failed to add assignee - could not get ID');\n }\n }\n const url = `projects/${\n config.repository\n }/merge_requests/${iid}?${getQueryString({\n 'assignee_ids[]': assigneeIds,\n })}`;\n await gitlabApi.putJson(url);\n } catch (err) {\n logger.debug({ err }, 'addAssignees error');\n logger.warn({ iid, assignees }, 'Failed to add assignees');\n }\n}\n\nexport async function addReviewers(\n iid: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${iid}`);\n\n if (semver.lt(defaults.version, '13.9.0')) {\n logger.warn(\n { version: defaults.version },\n 'Adding reviewers is only available in GitLab 13.9 and onwards',\n );\n return;\n }\n\n let mr: GitLabMergeRequest;\n try {\n mr = await getMR(config.repository, iid);\n } catch (err) {\n logger.warn({ err }, 'Failed to get existing reviewers');\n return;\n }\n\n mr.reviewers = coerceArray(mr.reviewers);\n const existingReviewers = mr.reviewers.map((r) => r.username);\n const existingReviewerIDs = mr.reviewers.map((r) => r.id);\n\n // Figure out which reviewers (of the ones we want to add) are not already on the MR as a reviewer\n const newReviewers = reviewers.filter((r) => !existingReviewers.includes(r));\n\n // Gather the IDs for all the reviewers we want to add\n let newReviewerIDs: number[];\n newReviewerIDs = (\n await p.all(\n newReviewers.map((r) => async () => {\n try {\n return [await getUserID(r)];\n } catch {\n // Unable to fetch userId, try resolve as a group\n return getMemberUserIDs(r);\n }\n }),\n )\n ).flat();\n\n if (isNonEmptyArray(newReviewers) && isEmptyArray(newReviewerIDs)) {\n logger.warn('Failed to get IDs of the new reviewers');\n return;\n }\n\n // Multiple groups may have the same members, so\n // filter out non-distinct values\n newReviewerIDs = [...new Set(newReviewerIDs)];\n\n try {\n await updateMR(config.repository, iid, {\n reviewer_ids: [...existingReviewerIDs, ...newReviewerIDs],\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to add reviewers');\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n try {\n const pr = await getPr(issueNo);\n const labels = coerceArray(pr.labels)\n .filter((l: string) => l !== label)\n .join(',');\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}`,\n {\n body: { labels },\n },\n );\n } catch (err) /* v8 ignore next -- defensive: label deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function getComments(issueNo: number): Promise<GitlabComment[]> {\n // GET projects/:owner/:repo/merge_requests/:number/notes\n logger.debug(`Getting comments for #${issueNo}`);\n const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`;\n const comments = (\n await gitlabApi.getJsonUnchecked<GitlabComment[]>(url, { paginate: true })\n ).body;\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST projects/:owner/:repo/merge_requests/:number/notes\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(\n issueNo: number,\n commentId: number,\n body: string,\n): Promise<void> {\n // PUT projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(\n issueNo: number,\n commentId: number,\n): Promise<void> {\n // DELETE projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.deleteJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n );\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n const massagedTopic = topic\n ? topic\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR')\n : topic;\n const comments = await getComments(number);\n let body: string;\n let commentId: number | undefined;\n let commentNeedsUpdating: boolean | undefined;\n // TODO: types (#22198)\n if (topic) {\n logger.debug(`Ensuring comment \"${massagedTopic!}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n body = smartTruncate(\n body\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR'),\n maxBodyLength(),\n );\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body.startsWith(`### ${massagedTopic!}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = smartTruncate(`${sanitizedContent}`, maxBodyLength());\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Added comment',\n );\n } else if (commentNeedsUpdating) {\n await editComment(number, commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Updated comment',\n );\n } else {\n logger.debug('Comment is already up-to-date');\n }\n return true;\n}\n\nfunction byTopic(comment: GitlabComment, topic: string): boolean {\n return comment.body.startsWith(`### ${topic}\\n\\n`);\n}\n\nfunction byContent(comment: GitlabComment, content: string): boolean {\n return comment.body.trim() === content;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const topic = deleteConfig.topic;\n commentId = comments.find((comment) => byTopic(comment, topic))?.id;\n } else if (deleteConfig.type === 'by-content') {\n const content = deleteConfig.content;\n commentId = comments.find((comment) => byContent(comment, content))?.id;\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n await deleteComment(issueNo, commentId);\n }\n}\n\nexport async function filterUnavailableUsers(\n users: string[],\n): Promise<string[]> {\n const filteredUsers: string[] = [];\n for (const user of users) {\n if (!(await isUserBusy(user))) {\n filteredUsers.push(user);\n }\n }\n return filteredUsers;\n}\n\nexport async function expandGroupMembers(\n reviewersOrAssignees: string[],\n): Promise<string[]> {\n const expandedReviewersOrAssignees: string[] = [];\n const normalizedReviewersOrAssigneesWithoutEmails: string[] = [];\n\n // Skip passing user emails to Gitlab API, but include them in the final result\n for (const reviewerOrAssignee of reviewersOrAssignees) {\n // Resolve GitLab CODEOWNERS role handles (@@developer, @@maintainer,\n // @@owner) to project members instead of treating them as groups\n const roleAccessLevel = getRoleAccessLevel(reviewerOrAssignee);\n if (roleAccessLevel !== null) {\n try {\n const members = await getProjectMembersByRole(\n config.repository,\n roleAccessLevel,\n );\n expandedReviewersOrAssignees.push(...members.map((u) => u.username));\n } catch (err) {\n logger.debug(\n { err, reviewerOrAssignee },\n 'Unable to fetch role members',\n );\n }\n continue;\n }\n\n if (reviewerOrAssignee.indexOf('@') > 0) {\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n continue;\n }\n\n // Normalize the potential group names before passing to Gitlab API\n normalizedReviewersOrAssigneesWithoutEmails.push(\n noLeadingAtSymbol(reviewerOrAssignee),\n );\n }\n\n for (const reviewerOrAssignee of normalizedReviewersOrAssigneesWithoutEmails) {\n try {\n const members = await getMemberUsernames(reviewerOrAssignee);\n expandedReviewersOrAssignees.push(...members);\n } catch (err) {\n if (!isNotFound(err)) {\n logger.debug({ err, reviewerOrAssignee }, 'Unable to fetch group');\n }\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n }\n }\n return expandedReviewersOrAssignees;\n}\n"],"mappings":"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"}
|
|
@@ -94,7 +94,10 @@ async function getBranchPr(branchName) {
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
async function findPr({ branchName, prTitle, state = "all" }) {
|
|
97
|
-
const result = (await getPrList()).find((pr) =>
|
|
97
|
+
const result = (await getPrList()).find((pr) => {
|
|
98
|
+
if (branchName !== pr.sourceBranch || !matchPrState(pr, state)) return false;
|
|
99
|
+
return !prTitle || prTitle === pr.title;
|
|
100
|
+
});
|
|
98
101
|
if (result) {
|
|
99
102
|
logger.debug({ result }, `Found PR`);
|
|
100
103
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["git.initRepo"],"sources":["../../../../lib/modules/platform/scm-manager/index.ts"],"sourcesContent":["import { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { getBaseUrl, setBaseUrl } from '../../../util/http/scm-manager.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfigByContent,\n EnsureCommentRemovalConfigByTopic,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { mapPrFromScmToRenovate } from './mapper.ts';\nimport {\n createScmPr,\n getAllRepoPrs,\n getAllRepos,\n getCurrentUser,\n getDefaultBranch,\n getRepo,\n getRepoPr,\n updateScmPr,\n} from './scm-manager-helper.ts';\nimport { getRepoUrl, mapPrState, matchPrState, smartLinks } from './utils.ts';\n\ninterface SCMMRepoConfig {\n repository: string;\n prList: Pr[] | null;\n defaultBranch: string;\n ignorePrAuthor: boolean;\n}\n\nexport const id = 'scm-manager';\nexport const experimental = true;\n\nlet config: SCMMRepoConfig = {} as any;\n\nexport async function initPlatform({\n endpoint,\n token,\n}: PlatformParams): Promise<PlatformResult> {\n if (!endpoint) {\n throw new Error('Init: SCM-Manager endpoint not configured');\n }\n\n if (!token) {\n throw new Error('Init: SCM-Manager API token not configured');\n }\n\n const baseUrl = `${ensureTrailingSlash(endpoint)}api/v2`;\n setBaseUrl(baseUrl);\n\n try {\n const me = await getCurrentUser(token);\n const gitAuthor = `${me.displayName} <${me.mail}>`;\n const result = { endpoint: baseUrl, gitAuthor };\n\n logger.debug({ result }, 'Platform result');\n\n return result;\n } catch (err) {\n logger.debug(\n { err },\n 'Init: Error authenticating with SCM-Manager. Check your token',\n );\n throw new Error('Init: Authentication failure');\n }\n}\n\nexport async function initRepo({\n repository,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n const repo = await getRepo(repository);\n const defaultBranch = await getDefaultBranch(repo);\n const url = getRepoUrl(repo, gitUrl, getBaseUrl());\n\n config = {} as any;\n config.repository = repository;\n config.defaultBranch = defaultBranch;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n await git.initRepo({\n ...config,\n url,\n });\n\n // Reset cached resources\n invalidatePrCache();\n\n const result = {\n defaultBranch: config.defaultBranch,\n isFork: false,\n repoFingerprint: repoFingerprint(config.repository, getBaseUrl()),\n };\n\n logger.debug({ result }, `Repo initialized`);\n\n return result;\n}\n\nexport async function getRepos(): Promise<string[]> {\n const repos = (await getAllRepos()).filter((repo) => repo.type === 'git');\n return repos.map((repo) => `${repo.namespace}/${repo.name}`);\n}\n\nexport async function getBranchPr(branchName: string): Promise<Pr | null> {\n return await findPr({ branchName, state: 'open' });\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n}: FindPRConfig): Promise<Pr | null> {\n const inProgressPrs = await getPrList();\n const result = inProgressPrs.find(\n (pr) =>\n branchName === pr.sourceBranch &&\n (!prTitle || prTitle === pr.title) &&\n matchPrState(pr, state),\n );\n\n if (result) {\n logger.debug({ result }, `Found PR`);\n return result;\n }\n\n logger.debug(\n `Could not find PR with source branch ${branchName} and title ${\n prTitle ?? ''\n } and state ${state}`,\n );\n\n return null;\n}\n\nexport async function getPr(number: number): Promise<Pr | null> {\n const inProgressPrs = await getPrList();\n const cachedPr = inProgressPrs.find((pr) => pr.number === number);\n\n if (cachedPr) {\n logger.debug('Returning from cached PRs');\n return cachedPr;\n }\n\n try {\n const result = await getRepoPr(config.repository, number);\n logger.debug('Returning PR from API');\n return mapPrFromScmToRenovate(result);\n } catch (err) {\n logger.error({ err, number }, 'Can not find a PR with the given id');\n return null;\n }\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n if (config.prList === null) {\n try {\n config.prList = (\n await getAllRepoPrs(config.repository, config.ignorePrAuthor)\n ).map((pr) => mapPrFromScmToRenovate(pr));\n } catch (error) {\n logger.error(error);\n }\n }\n\n return coerceArray(config.prList);\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody,\n draftPR,\n}: CreatePRConfig): Promise<Pr> {\n const createdPr = await createScmPr(config.repository, {\n source: sourceBranch,\n target: targetBranch,\n title: prTitle,\n description: sanitize(prBody),\n status: draftPR ? 'DRAFT' : 'OPEN',\n });\n\n logger.debug(\n `PR created with title '${createdPr.title}' from source '${createdPr.source}' to target '${createdPr.target}'`,\n );\n\n return mapPrFromScmToRenovate(createdPr);\n}\n\nexport async function updatePr({\n number,\n prTitle,\n prBody,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n await updateScmPr(config.repository, number, {\n title: prTitle,\n description: sanitize(prBody) ?? undefined,\n target: targetBranch,\n status: mapPrState(state),\n });\n\n logger.debug(`Updated PR #${number} with title ${prTitle}`);\n}\n\nexport function mergePr(_config: MergePRConfig): Promise<boolean> {\n logger.debug('Not implemented mergePr');\n return Promise.resolve(false);\n}\n\nexport function getBranchStatus(\n _branchName: string,\n _internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug('Not implemented getBranchStatus');\n return Promise.resolve('red');\n}\n\nexport function setBranchStatus(\n _branchStatusConfig: BranchStatusConfig,\n): Promise<void> {\n logger.debug('Not implemented setBranchStatus');\n return Promise.resolve();\n}\n\nexport function getBranchStatusCheck(\n _branchName: string,\n _context: string,\n): Promise<BranchStatus | null> {\n logger.debug('Not implemented setBranchStatus');\n return Promise.resolve(null);\n}\n\nexport function addReviewers(\n _number: number,\n _reviewers: string[],\n): Promise<void> {\n logger.debug('Not implemented addReviewers');\n return Promise.resolve();\n}\n\nexport function addAssignees(\n _number: number,\n _assignees: string[],\n): Promise<void> {\n logger.debug('Not implemented addAssignees');\n return Promise.resolve();\n}\n\nexport function deleteLabel(_number: number, _label: string): Promise<void> {\n logger.debug('Not implemented deleteLabel');\n return Promise.resolve();\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n logger.debug('Not implemented getIssueList');\n return Promise.resolve([]);\n}\n\nexport function findIssue(_title: string): Promise<Issue | null> {\n logger.debug('Not implemented findIssue');\n return Promise.resolve(null);\n}\n\nexport function ensureIssue(\n _config: EnsureIssueConfig,\n): Promise<'updated' | 'created' | null> {\n logger.debug('Not implemented ensureIssue');\n return Promise.resolve(null);\n}\n\nexport function ensureIssueClosing(_title: string): Promise<void> {\n logger.debug('Not implemented ensureIssueClosing');\n return Promise.resolve();\n}\n\nexport function ensureComment(_config: EnsureCommentConfig): Promise<boolean> {\n logger.debug('Not implemented ensureComment');\n return Promise.resolve(false);\n}\n\nexport function ensureCommentRemoval(\n _ensureCommentRemoval:\n EnsureCommentRemovalConfigByTopic | EnsureCommentRemovalConfigByContent,\n): Promise<void> {\n logger.debug('Not implemented ensureCommentRemoval');\n return Promise.resolve();\n}\n\nexport function massageMarkdown(prBody: string): string {\n return smartTruncate(smartLinks(prBody), maxBodyLength());\n}\n\nexport function getRawFile(\n _fileName: string,\n _repoName?: string,\n _branchOrTag?: string,\n): Promise<string | null> {\n logger.debug('Not implemented getRawFile');\n return Promise.resolve(null);\n}\n\nexport function getJsonFile(\n _fileName: string,\n _repoName?: string,\n _branchOrTag?: string,\n): Promise<any> {\n logger.debug('Not implemented getJsonFile');\n return Promise.resolve(null);\n}\n\nexport function maxBodyLength(): number {\n return 200000;\n}\n\nexport function invalidatePrCache(): void {\n config.prList = null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["git.initRepo"],"sources":["../../../../lib/modules/platform/scm-manager/index.ts"],"sourcesContent":["import { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { getBaseUrl, setBaseUrl } from '../../../util/http/scm-manager.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfigByContent,\n EnsureCommentRemovalConfigByTopic,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { mapPrFromScmToRenovate } from './mapper.ts';\nimport {\n createScmPr,\n getAllRepoPrs,\n getAllRepos,\n getCurrentUser,\n getDefaultBranch,\n getRepo,\n getRepoPr,\n updateScmPr,\n} from './scm-manager-helper.ts';\nimport { getRepoUrl, mapPrState, matchPrState, smartLinks } from './utils.ts';\n\ninterface SCMMRepoConfig {\n repository: string;\n prList: Pr[] | null;\n defaultBranch: string;\n ignorePrAuthor: boolean;\n}\n\nexport const id = 'scm-manager';\nexport const experimental = true;\n\nlet config: SCMMRepoConfig = {} as any;\n\nexport async function initPlatform({\n endpoint,\n token,\n}: PlatformParams): Promise<PlatformResult> {\n if (!endpoint) {\n throw new Error('Init: SCM-Manager endpoint not configured');\n }\n\n if (!token) {\n throw new Error('Init: SCM-Manager API token not configured');\n }\n\n const baseUrl = `${ensureTrailingSlash(endpoint)}api/v2`;\n setBaseUrl(baseUrl);\n\n try {\n const me = await getCurrentUser(token);\n const gitAuthor = `${me.displayName} <${me.mail}>`;\n const result = { endpoint: baseUrl, gitAuthor };\n\n logger.debug({ result }, 'Platform result');\n\n return result;\n } catch (err) {\n logger.debug(\n { err },\n 'Init: Error authenticating with SCM-Manager. Check your token',\n );\n throw new Error('Init: Authentication failure');\n }\n}\n\nexport async function initRepo({\n repository,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n const repo = await getRepo(repository);\n const defaultBranch = await getDefaultBranch(repo);\n const url = getRepoUrl(repo, gitUrl, getBaseUrl());\n\n config = {} as any;\n config.repository = repository;\n config.defaultBranch = defaultBranch;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n await git.initRepo({\n ...config,\n url,\n });\n\n // Reset cached resources\n invalidatePrCache();\n\n const result = {\n defaultBranch: config.defaultBranch,\n isFork: false,\n repoFingerprint: repoFingerprint(config.repository, getBaseUrl()),\n };\n\n logger.debug({ result }, `Repo initialized`);\n\n return result;\n}\n\nexport async function getRepos(): Promise<string[]> {\n const repos = (await getAllRepos()).filter((repo) => repo.type === 'git');\n return repos.map((repo) => `${repo.namespace}/${repo.name}`);\n}\n\nexport async function getBranchPr(branchName: string): Promise<Pr | null> {\n return await findPr({ branchName, state: 'open' });\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n}: FindPRConfig): Promise<Pr | null> {\n const inProgressPrs = await getPrList();\n const result = inProgressPrs.find((pr) => {\n if (branchName !== pr.sourceBranch || !matchPrState(pr, state)) {\n return false;\n }\n return !prTitle || prTitle === pr.title;\n });\n\n if (result) {\n logger.debug({ result }, `Found PR`);\n return result;\n }\n\n logger.debug(\n `Could not find PR with source branch ${branchName} and title ${\n prTitle ?? ''\n } and state ${state}`,\n );\n\n return null;\n}\n\nexport async function getPr(number: number): Promise<Pr | null> {\n const inProgressPrs = await getPrList();\n const cachedPr = inProgressPrs.find((pr) => pr.number === number);\n\n if (cachedPr) {\n logger.debug('Returning from cached PRs');\n return cachedPr;\n }\n\n try {\n const result = await getRepoPr(config.repository, number);\n logger.debug('Returning PR from API');\n return mapPrFromScmToRenovate(result);\n } catch (err) {\n logger.error({ err, number }, 'Can not find a PR with the given id');\n return null;\n }\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n if (config.prList === null) {\n try {\n config.prList = (\n await getAllRepoPrs(config.repository, config.ignorePrAuthor)\n ).map((pr) => mapPrFromScmToRenovate(pr));\n } catch (error) {\n logger.error(error);\n }\n }\n\n return coerceArray(config.prList);\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody,\n draftPR,\n}: CreatePRConfig): Promise<Pr> {\n const createdPr = await createScmPr(config.repository, {\n source: sourceBranch,\n target: targetBranch,\n title: prTitle,\n description: sanitize(prBody),\n status: draftPR ? 'DRAFT' : 'OPEN',\n });\n\n logger.debug(\n `PR created with title '${createdPr.title}' from source '${createdPr.source}' to target '${createdPr.target}'`,\n );\n\n return mapPrFromScmToRenovate(createdPr);\n}\n\nexport async function updatePr({\n number,\n prTitle,\n prBody,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n await updateScmPr(config.repository, number, {\n title: prTitle,\n description: sanitize(prBody) ?? undefined,\n target: targetBranch,\n status: mapPrState(state),\n });\n\n logger.debug(`Updated PR #${number} with title ${prTitle}`);\n}\n\nexport function mergePr(_config: MergePRConfig): Promise<boolean> {\n logger.debug('Not implemented mergePr');\n return Promise.resolve(false);\n}\n\nexport function getBranchStatus(\n _branchName: string,\n _internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug('Not implemented getBranchStatus');\n return Promise.resolve('red');\n}\n\nexport function setBranchStatus(\n _branchStatusConfig: BranchStatusConfig,\n): Promise<void> {\n logger.debug('Not implemented setBranchStatus');\n return Promise.resolve();\n}\n\nexport function getBranchStatusCheck(\n _branchName: string,\n _context: string,\n): Promise<BranchStatus | null> {\n logger.debug('Not implemented setBranchStatus');\n return Promise.resolve(null);\n}\n\nexport function addReviewers(\n _number: number,\n _reviewers: string[],\n): Promise<void> {\n logger.debug('Not implemented addReviewers');\n return Promise.resolve();\n}\n\nexport function addAssignees(\n _number: number,\n _assignees: string[],\n): Promise<void> {\n logger.debug('Not implemented addAssignees');\n return Promise.resolve();\n}\n\nexport function deleteLabel(_number: number, _label: string): Promise<void> {\n logger.debug('Not implemented deleteLabel');\n return Promise.resolve();\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n logger.debug('Not implemented getIssueList');\n return Promise.resolve([]);\n}\n\nexport function findIssue(_title: string): Promise<Issue | null> {\n logger.debug('Not implemented findIssue');\n return Promise.resolve(null);\n}\n\nexport function ensureIssue(\n _config: EnsureIssueConfig,\n): Promise<'updated' | 'created' | null> {\n logger.debug('Not implemented ensureIssue');\n return Promise.resolve(null);\n}\n\nexport function ensureIssueClosing(_title: string): Promise<void> {\n logger.debug('Not implemented ensureIssueClosing');\n return Promise.resolve();\n}\n\nexport function ensureComment(_config: EnsureCommentConfig): Promise<boolean> {\n logger.debug('Not implemented ensureComment');\n return Promise.resolve(false);\n}\n\nexport function ensureCommentRemoval(\n _ensureCommentRemoval:\n EnsureCommentRemovalConfigByTopic | EnsureCommentRemovalConfigByContent,\n): Promise<void> {\n logger.debug('Not implemented ensureCommentRemoval');\n return Promise.resolve();\n}\n\nexport function massageMarkdown(prBody: string): string {\n return smartTruncate(smartLinks(prBody), maxBodyLength());\n}\n\nexport function getRawFile(\n _fileName: string,\n _repoName?: string,\n _branchOrTag?: string,\n): Promise<string | null> {\n logger.debug('Not implemented getRawFile');\n return Promise.resolve(null);\n}\n\nexport function getJsonFile(\n _fileName: string,\n _repoName?: string,\n _branchOrTag?: string,\n): Promise<any> {\n logger.debug('Not implemented getJsonFile');\n return Promise.resolve(null);\n}\n\nexport function maxBodyLength(): number {\n return 200000;\n}\n\nexport function invalidatePrCache(): void {\n config.prList = null;\n}\n"],"mappings":"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"}
|
|
@@ -12,7 +12,8 @@ function mapPrState(state) {
|
|
|
12
12
|
}
|
|
13
13
|
function matchPrState(pr, state) {
|
|
14
14
|
if (state === "all") return true;
|
|
15
|
-
|
|
15
|
+
const isClosed = pr.state === "closed" || pr.state === "merged";
|
|
16
|
+
if (state === "!open" && isClosed) return true;
|
|
16
17
|
return state === pr.state;
|
|
17
18
|
}
|
|
18
19
|
function smartLinks(body) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/scm-manager/utils.ts"],"sourcesContent":["import type { MergeStrategy } from '../../../config/types.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { GitUrlOption, Pr } from '../types.ts';\nimport type { PrMergeMethod, Repo } from './schema.ts';\nimport type { PrFilterByState } from './types.ts';\n\nexport function mapPrState(\n state: 'open' | 'closed' | undefined,\n): 'OPEN' | 'REJECTED' | undefined {\n switch (state) {\n case 'open':\n return 'OPEN';\n case 'closed':\n return 'REJECTED';\n default:\n return undefined;\n }\n}\n\nexport function matchPrState(pr: Pr, state: PrFilterByState): boolean {\n if (state === 'all') {\n return true;\n }\n\n
|
|
1
|
+
{"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/scm-manager/utils.ts"],"sourcesContent":["import type { MergeStrategy } from '../../../config/types.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { GitUrlOption, Pr } from '../types.ts';\nimport type { PrMergeMethod, Repo } from './schema.ts';\nimport type { PrFilterByState } from './types.ts';\n\nexport function mapPrState(\n state: 'open' | 'closed' | undefined,\n): 'OPEN' | 'REJECTED' | undefined {\n switch (state) {\n case 'open':\n return 'OPEN';\n case 'closed':\n return 'REJECTED';\n default:\n return undefined;\n }\n}\n\nexport function matchPrState(pr: Pr, state: PrFilterByState): boolean {\n if (state === 'all') {\n return true;\n }\n\n const isClosed = pr.state === 'closed' || pr.state === 'merged';\n if (state === '!open' && isClosed) {\n return true;\n }\n\n return state === pr.state;\n}\n\nexport function smartLinks(body: string): string {\n return body.replace(regEx(/]\\(\\.\\.\\/pull\\//g), '](pulls/');\n}\n\nexport function getRepoUrl(\n repo: Repo,\n gitUrl: GitUrlOption | undefined,\n endpoint: string,\n): string {\n const protocolLinks = repo._links.protocol;\n\n if (!protocolLinks) {\n throw new Error('Missing protocol links.');\n }\n\n if (!Array.isArray(protocolLinks)) {\n throw new Error('Expected protocol links to be an array of links.');\n }\n\n if (gitUrl === 'ssh') {\n const sshUrl = protocolLinks.find((l) => l.name === 'ssh')?.href;\n if (!sshUrl) {\n throw new Error('MISSING_SSH_LINKS');\n }\n\n logger.debug(`Using SSH URL: ${sshUrl}`);\n return sshUrl;\n }\n\n const httpUrl = protocolLinks.find((l) => l.name === 'http')?.href;\n if (!httpUrl) {\n throw new Error('MISSING_HTTP_LINK');\n }\n\n logger.debug(`Using HTTP URL: ${httpUrl}`);\n\n const repoUrl = parseUrl(httpUrl);\n if (!repoUrl) {\n throw new Error('MALFORMED_HTTP_LINK');\n }\n\n const hostOptions = hostRules.find({\n hostType: 'scm-manager',\n url: endpoint,\n });\n\n // SCM-Manager ignores the username for API keys, `x-access-token` is our own choice and not documented by SCM-Manager\n repoUrl.username = hostOptions.username ?? 'x-access-token';\n repoUrl.password = hostOptions.token ?? '';\n\n return repoUrl.toString();\n}\n\nexport function getMergeMethod(\n strategy: MergeStrategy | undefined,\n): PrMergeMethod | null {\n switch (strategy) {\n case 'fast-forward':\n return 'FAST_FORWARD_ONLY';\n case 'merge-commit':\n return 'MERGE_COMMIT';\n case 'rebase':\n return 'REBASE';\n case 'squash':\n return 'SQUASH';\n default:\n return null;\n }\n}\n"],"mappings":";;;;;AASA,SAAgB,WACd,OACiC;CACjC,QAAQ,OAAR;EACE,KAAK,QACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,SACE;CACJ;AACF;AAEA,SAAgB,aAAa,IAAQ,OAAiC;CACpE,IAAI,UAAU,OACZ,OAAO;CAGT,MAAM,WAAW,GAAG,UAAU,YAAY,GAAG,UAAU;CACvD,IAAI,UAAU,WAAW,UACvB,OAAO;CAGT,OAAO,UAAU,GAAG;AACtB;AAEA,SAAgB,WAAW,MAAsB;CAC/C,OAAO,KAAK,QAAQ,MAAM,kBAAkB,GAAG,UAAU;AAC3D;AAEA,SAAgB,WACd,MACA,QACA,UACQ;CACR,MAAM,gBAAgB,KAAK,OAAO;CAElC,IAAI,CAAC,eACH,MAAM,IAAI,MAAM,yBAAyB;CAG3C,IAAI,CAAC,MAAM,QAAQ,aAAa,GAC9B,MAAM,IAAI,MAAM,kDAAkD;CAGpE,IAAI,WAAW,OAAO;EACpB,MAAM,SAAS,cAAc,MAAM,MAAM,EAAE,SAAS,KAAK,CAAC,EAAE;EAC5D,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,mBAAmB;EAGrC,OAAO,MAAM,kBAAkB,QAAQ;EACvC,OAAO;CACT;CAEA,MAAM,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE;CAC9D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mBAAmB;CAGrC,OAAO,MAAM,mBAAmB,SAAS;CAEzC,MAAM,UAAU,SAAS,OAAO;CAChC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qBAAqB;CAGvC,MAAM,cAAcA,KAAe;EACjC,UAAU;EACV,KAAK;CACP,CAAC;CAGD,QAAQ,WAAW,YAAY,YAAY;CAC3C,QAAQ,WAAW,YAAY,SAAS;CAExC,OAAO,QAAQ,SAAS;AAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["npm","semver","getMajor","getMinor"],"sources":["../../../../lib/modules/versioning/cargo/index.ts"],"sourcesContent":["import { major as getMajor, minor as getMinor } from 'semver';\nimport semver from 'semver-stable';\nimport { logger } from '../../../logger/index.ts';\nimport type { RangeStrategy } from '../../../types/versioning.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { api as npm } from '../npm/index.ts';\nimport type { NewValueConfig, VersioningApi } from '../types.ts';\n\nexport const id = 'cargo';\nexport const displayName = 'Cargo';\nexport const urls = [\n '[Cargo - Specifying Dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)',\n];\nexport const supportsRanges = true;\nexport const supportedRangeStrategies: RangeStrategy[] = ['bump', 'replace'];\n\nfunction isVersion(input: string): boolean {\n return npm.isVersion(input);\n}\n\nfunction convertToCaret(item: string): string {\n // In Cargo, caret versions are used by default, so \"1.2.3\" actually means ^1.2.3.\n // Similarly, \"0.4\" actually means ^0.4.\n // See: https://doc.rust-lang.org/stable/cargo/reference/specifying-dependencies.html#caret-requirements\n if (isVersion(item) || isVersion(`${item}.0`) || isVersion(`${item}.0.0`)) {\n return `^${item.trim()}`;\n }\n return item.trim();\n}\n\nfunction cargo2npm(input: string): string {\n let versions = input.split(',');\n versions = versions.map(convertToCaret);\n return versions.join(' ');\n}\n\nfunction notEmpty(s: string): boolean {\n return s !== '';\n}\n\nfunction npm2cargo(input: string): string {\n // istanbul ignore if\n if (!input) {\n return input;\n }\n // Note: this doesn't remove the ^\n const res = input\n .split(regEx(/\\s+,?\\s*|\\s*,?\\s+/))\n .map((str) => str.trim())\n .filter(notEmpty);\n const operators = ['^', '~', '=', '>', '<', '<=', '>='];\n for (let i = 0; i < res.length - 1; i += 1) {\n if (operators.includes(res[i])) {\n const newValue = `${res[i]} ${res[i + 1]}`;\n res.splice(i, 2, newValue);\n }\n }\n return res.join(', ');\n}\n\nfunction isLessThanRange(version: string, range: string): boolean {\n return !!npm.isLessThanRange?.(version, cargo2npm(range));\n}\n\nexport function isValid(input: string): boolean {\n return npm.isValid(cargo2npm(input));\n}\n\nfunction matches(version: string, range: string): boolean {\n return npm.matches(version, cargo2npm(range));\n}\n\nfunction getSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return npm.getSatisfyingVersion(versions, cargo2npm(range));\n}\n\nfunction minSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return npm.minSatisfyingVersion(versions, cargo2npm(range));\n}\n\nfunction isSingleVersion(constraint: string): boolean {\n return (\n constraint.trim().startsWith('=') &&\n isVersion(constraint.trim().substring(1).trim())\n );\n}\n\nfunction getPinnedValue(newVersion: string): string {\n return `=${newVersion}`;\n}\n\nfunction getNewValue({\n currentValue,\n rangeStrategy,\n currentVersion,\n newVersion,\n}: NewValueConfig): string {\n if (!currentValue || currentValue === '*') {\n return currentValue;\n }\n // If the current value is a simple version, bump to fully specified newVersion\n if (rangeStrategy === 'bump' && regEx(/^\\d+(?:\\.\\d+)*$/).test(currentValue)) {\n return newVersion;\n }\n if (isSingleVersion(currentValue)) {\n let res = '=';\n if (currentValue.startsWith('= ')) {\n res += ' ';\n }\n res += newVersion;\n return res;\n }\n if (rangeStrategy === 'replace' && matches(newVersion, currentValue)) {\n return currentValue;\n }\n const newSemver = npm.getNewValue({\n currentValue: cargo2npm(currentValue),\n rangeStrategy,\n currentVersion,\n newVersion,\n });\n let newCargo = newSemver\n ? npm2cargo(newSemver)\n : /* istanbul ignore next: should never happen */ null;\n // istanbul ignore if\n if (!newCargo) {\n logger.info(\n { currentValue, newSemver },\n 'Could not get cargo version from semver',\n );\n return currentValue;\n }\n // Keep new range precision the same as current\n
|
|
1
|
+
{"version":3,"file":"index.js","names":["npm","semver","getMajor","getMinor"],"sources":["../../../../lib/modules/versioning/cargo/index.ts"],"sourcesContent":["import { major as getMajor, minor as getMinor } from 'semver';\nimport semver from 'semver-stable';\nimport { logger } from '../../../logger/index.ts';\nimport type { RangeStrategy } from '../../../types/versioning.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { api as npm } from '../npm/index.ts';\nimport type { NewValueConfig, VersioningApi } from '../types.ts';\n\nexport const id = 'cargo';\nexport const displayName = 'Cargo';\nexport const urls = [\n '[Cargo - Specifying Dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)',\n];\nexport const supportsRanges = true;\nexport const supportedRangeStrategies: RangeStrategy[] = ['bump', 'replace'];\n\nfunction isVersion(input: string): boolean {\n return npm.isVersion(input);\n}\n\nfunction convertToCaret(item: string): string {\n // In Cargo, caret versions are used by default, so \"1.2.3\" actually means ^1.2.3.\n // Similarly, \"0.4\" actually means ^0.4.\n // See: https://doc.rust-lang.org/stable/cargo/reference/specifying-dependencies.html#caret-requirements\n if (isVersion(item) || isVersion(`${item}.0`) || isVersion(`${item}.0.0`)) {\n return `^${item.trim()}`;\n }\n return item.trim();\n}\n\nfunction cargo2npm(input: string): string {\n let versions = input.split(',');\n versions = versions.map(convertToCaret);\n return versions.join(' ');\n}\n\nfunction notEmpty(s: string): boolean {\n return s !== '';\n}\n\nfunction npm2cargo(input: string): string {\n // istanbul ignore if\n if (!input) {\n return input;\n }\n // Note: this doesn't remove the ^\n const res = input\n .split(regEx(/\\s+,?\\s*|\\s*,?\\s+/))\n .map((str) => str.trim())\n .filter(notEmpty);\n const operators = ['^', '~', '=', '>', '<', '<=', '>='];\n for (let i = 0; i < res.length - 1; i += 1) {\n if (operators.includes(res[i])) {\n const newValue = `${res[i]} ${res[i + 1]}`;\n res.splice(i, 2, newValue);\n }\n }\n return res.join(', ');\n}\n\nfunction isLessThanRange(version: string, range: string): boolean {\n return !!npm.isLessThanRange?.(version, cargo2npm(range));\n}\n\nexport function isValid(input: string): boolean {\n return npm.isValid(cargo2npm(input));\n}\n\nfunction matches(version: string, range: string): boolean {\n return npm.matches(version, cargo2npm(range));\n}\n\nfunction getSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return npm.getSatisfyingVersion(versions, cargo2npm(range));\n}\n\nfunction minSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return npm.minSatisfyingVersion(versions, cargo2npm(range));\n}\n\nfunction isSingleVersion(constraint: string): boolean {\n return (\n constraint.trim().startsWith('=') &&\n isVersion(constraint.trim().substring(1).trim())\n );\n}\n\nfunction getPinnedValue(newVersion: string): string {\n return `=${newVersion}`;\n}\n\nfunction getNewValue({\n currentValue,\n rangeStrategy,\n currentVersion,\n newVersion,\n}: NewValueConfig): string {\n if (!currentValue || currentValue === '*') {\n return currentValue;\n }\n // If the current value is a simple version, bump to fully specified newVersion\n if (rangeStrategy === 'bump' && regEx(/^\\d+(?:\\.\\d+)*$/).test(currentValue)) {\n return newVersion;\n }\n if (isSingleVersion(currentValue)) {\n let res = '=';\n if (currentValue.startsWith('= ')) {\n res += ' ';\n }\n res += newVersion;\n return res;\n }\n if (rangeStrategy === 'replace' && matches(newVersion, currentValue)) {\n return currentValue;\n }\n const newSemver = npm.getNewValue({\n currentValue: cargo2npm(currentValue),\n rangeStrategy,\n currentVersion,\n newVersion,\n });\n let newCargo = newSemver\n ? npm2cargo(newSemver)\n : /* istanbul ignore next: should never happen */ null;\n // istanbul ignore if\n if (!newCargo) {\n logger.info(\n { currentValue, newSemver },\n 'Could not get cargo version from semver',\n );\n return currentValue;\n }\n // Keep new range precision the same as current\n const isTildeOrCaret =\n currentValue.startsWith('~') || currentValue.startsWith('^');\n if (\n isTildeOrCaret &&\n rangeStrategy === 'replace' &&\n newCargo.split('.').length > currentValue.split('.').length\n ) {\n newCargo = newCargo\n .split('.')\n .slice(0, currentValue.split('.').length)\n .join('.');\n }\n // Try to reverse any caret we added\n if (newCargo.startsWith('^') && !currentValue.startsWith('^')) {\n const withoutCaret = newCargo.substring(1);\n // NOTE: We want the number of components in the new version to match the original.\n // e.g. \"5.0\" should be updated to \"6.0\".\n const components = currentValue.split('.').length;\n newCargo = withoutCaret.split('.').slice(0, components).join('.');\n }\n\n return newCargo;\n}\n\nfunction subset(subRange: string, superRange: string): boolean | undefined {\n try {\n return npm.subset!(cargo2npm(subRange), cargo2npm(superRange));\n } catch (err) {\n logger.debug({ err }, 'cargo.subset error');\n return false;\n }\n}\n\nfunction intersects(subRange: string, superRange: string): boolean {\n try {\n return npm.intersects!(cargo2npm(subRange), cargo2npm(superRange));\n } catch (err) {\n logger.debug({ err }, 'cargo.intersects error');\n return false;\n }\n}\n\nfunction isBreaking(current: string, version: string): boolean {\n // The change may be breaking if either version is unstable\n if (!semver.is(version) || !semver.is(current)) {\n return true;\n }\n const currentMajor = getMajor(current);\n if (currentMajor === 0) {\n if (getMinor(current) === 0) {\n // This can only be non-breaking if they're the same version\n return current !== version;\n }\n // v0.x updates are breaking if x changes\n return getMinor(current) !== getMinor(version);\n }\n // Otherwise, only major updates are breaking\n return currentMajor !== getMajor(version);\n}\n\nexport const api: VersioningApi = {\n ...npm,\n getNewValue,\n getPinnedValue,\n isBreaking,\n isLessThanRange,\n isSingleVersion,\n isValid,\n matches,\n getSatisfyingVersion,\n minSatisfyingVersion,\n subset,\n intersects,\n};\nexport default api;\n"],"mappings":"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"}
|