UNPKG

renovate

Version:

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

170 lines (169 loc) • 7.47 kB
import { REPOSITORY_ARCHIVED } from "../../../constants/error-messages.js"; import { logger } from "../../../logger/index.js"; import { getQueryString } from "../../../util/url.js"; import { GerritHttp } from "../../../util/http/gerrit.js"; import { GerritBranchInfo, GerritChange, GerritChangeMessages, GerritChanges, GerritMergeableInfo, GerritProjectInfo, GerritRepos } from "./schema.js"; import { MAX_GERRIT_COMMENT_SIZE, MIN_GERRIT_VERSION, mapPrStateToGerritFilter } from "./utils.js"; import { isNonEmptyArray } from "@sindresorhus/is"; import { z } from "zod/v4"; import semver from "semver"; //#region lib/modules/platform/gerrit/client.ts var GerritClient = class { gerritHttp = new GerritHttp({ memCache: false }); gerritVersion = MIN_GERRIT_VERSION; setGerritVersion(version) { this.gerritVersion = version; } async getGerritVersion(options) { return (await this.gerritHttp.getJson("a/config/server/version", options, z.string())).body; } async getRepos() { const res = await this.gerritHttp.getJson("a/projects/?type=CODE&state=ACTIVE", GerritRepos); return Object.keys(res.body); } async getProjectInfo(repository) { const projectInfo = await this.gerritHttp.getJson(`a/projects/${encodeURIComponent(repository)}`, GerritProjectInfo); if (projectInfo.body.state !== "ACTIVE") throw new Error(REPOSITORY_ARCHIVED); return projectInfo.body; } async getBranchInfo(repository) { return (await this.gerritHttp.getJson(`a/projects/${encodeURIComponent(repository)}/branches/HEAD`, GerritBranchInfo)).body; } async getBranchChange(repository, config) { const changes = await this.findChanges(repository, { branchName: config.branchName, state: config.state, singleChange: config.targetBranch ? false : true, requestDetails: config.requestDetails }); if (changes.length === 0) return null; if (changes.length === 1) return changes[0]; if (config.targetBranch) { const change = changes.find((c) => c.branch === config.targetBranch); if (change) return change; } return changes[0]; } async findChanges(repository, findPRConfig) { const startOffset = findPRConfig.startOffset ?? 0; const query = { n: findPRConfig.singleChange ? 1 : findPRConfig.pageLimit ?? 50 }; if (findPRConfig.requestDetails) query.o = findPRConfig.requestDetails; const filters = this.buildSearchFilters(repository, findPRConfig); const allChanges = []; while (true) { query.S = allChanges.length + startOffset; const queryString = `q=${filters.join("+")}&${getQueryString(query)}`; const changes = await this.gerritHttp.getJson(`a/changes/?${queryString}`, GerritChanges); logger.trace(`findChanges(${queryString},start=${query.S},limit=${query.n}) => ${changes.body.length}`); const lastChange = changes.body.at(-1); let hasMoreChanges = false; if (lastChange?._more_changes) { hasMoreChanges = true; delete lastChange._more_changes; } allChanges.push(...changes.body); if (findPRConfig.singleChange || findPRConfig.noPagination || !hasMoreChanges) break; } return allChanges; } async getChange(changeNumber, requestDetails) { const queryString = getQueryString({ o: requestDetails }); return (await this.gerritHttp.getJson(`a/changes/${changeNumber}?${queryString}`, GerritChange)).body; } async getMergeableInfo(change) { return (await this.gerritHttp.getJson(`a/changes/${change._number}/revisions/current/mergeable`, GerritMergeableInfo)).body; } async abandonChange(changeNumber, message) { await this.gerritHttp.postJson(`a/changes/${changeNumber}/abandon`, { body: { message, notify: "OWNER_REVIEWERS" } }); } async submitChange(changeNumber) { return (await this.gerritHttp.postJson(`a/changes/${changeNumber}/submit`)).body; } async getMessages(changeNumber) { return (await this.gerritHttp.getJson(`a/changes/${changeNumber}/messages`, GerritChangeMessages)).body; } async addMessage(changeNumber, fullMessage, tag) { const message = this.normalizeMessage(fullMessage); await this.gerritHttp.postJson(`a/changes/${changeNumber}/revisions/current/review`, { body: { message, tag, notify: "NONE" } }); } async checkForExistingMessage(changeNumber, newMessage, msgType) { return (await this.getMessages(changeNumber)).some((existingMsg) => (msgType === void 0 || msgType === existingMsg.tag) && existingMsg.message.includes(newMessage)); } async addMessageIfNotAlreadyExists(changeNumber, message, tag) { const newMsg = this.normalizeMessage(message); if (!await this.checkForExistingMessage(changeNumber, newMsg, tag)) await this.addMessage(changeNumber, newMsg, tag); } async setLabel(changeNumber, label, value) { await this.gerritHttp.postJson(`a/changes/${changeNumber}/revisions/current/review`, { body: { labels: { [label]: value }, notify: "NONE" } }); } async setHashtags(changeNumber, hashtagsInput) { const { add, remove } = hashtagsInput; if (isNonEmptyArray(add) || isNonEmptyArray(remove)) await this.gerritHttp.postJson(`a/changes/${changeNumber}/hashtags`, { body: { add, remove } }); } async addReviewers(changeNumber, reviewers) { await this.gerritHttp.postJson(`a/changes/${changeNumber}/revisions/current/review`, { body: { reviewers: reviewers.map((r) => ({ reviewer: r })), notify: "OWNER_REVIEWERS" } }); } async addAssignee(changeNumber, assignee) { await this.gerritHttp.putJson(`a/changes/${changeNumber}/assignee`, { body: { assignee } }); } async getFile(repo, branch, fileName) { const base64Content = await this.gerritHttp.getText(`a/projects/${encodeURIComponent(repo)}/branches/${encodeURIComponent(branch)}/files/${encodeURIComponent(fileName)}/content`); return Buffer.from(base64Content.body, "base64").toString(); } async moveChange(changeNumber, destinationBranch) { return (await this.gerritHttp.postJson(`a/changes/${changeNumber}/move`, { body: { destination_branch: destinationBranch } })).body; } normalizeMessage(message) { let msg = message.trim(); const encoder = new TextEncoder(); const bytes = encoder.encode(msg); if (bytes.length > 16384) { const truncationNotice = "\n\n[Truncated by Renovate]"; const maxContentBytes = MAX_GERRIT_COMMENT_SIZE - encoder.encode(truncationNotice).length; const truncatedBytes = bytes.slice(0, maxContentBytes); msg = new TextDecoder().decode(truncatedBytes) + truncationNotice; } return msg; } buildSearchFilters(repository, searchConfig) { const filters = [ "owner:self", `project:${repository}`, "-is:wip", "-is:private" ]; const filterState = mapPrStateToGerritFilter(searchConfig.state); if (filterState) filters.push(filterState); if (searchConfig.branchName) filters.push(`footer:Renovate-Branch=${searchConfig.branchName}`); else if (semver.gte(this.gerritVersion, "3.6.0")) filters.push("hasfooter:Renovate-Branch"); else filters.push("message:\"Renovate-Branch: \""); if (searchConfig.targetBranch) filters.push(`branch:${searchConfig.targetBranch}`); if (searchConfig.label) filters.push(`label:Code-Review=${searchConfig.label}`); if (searchConfig.prTitle) { const escapedTitle = searchConfig.prTitle.replaceAll("\"", "\\\""); if (semver.gte(this.gerritVersion, "3.8.0")) filters.push(`subject:"${escapedTitle}"`); else filters.push(`message:"${escapedTitle}"`); } return filters; } }; const client = new GerritClient(); //#endregion export { client }; //# sourceMappingURL=client.js.map