UNPKG

renovate

Version:

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

160 lines • 7.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.client = void 0; const error_messages_1 = require("../../../constants/error-messages"); const logger_1 = require("../../../logger"); const memory_http_cache_provider_1 = require("../../../util/http/cache/memory-http-cache-provider"); const gerrit_1 = require("../../../util/http/gerrit"); const regex_1 = require("../../../util/regex"); const utils_1 = require("./utils"); const QUOTES_REGEX = (0, regex_1.regEx)('"', 'g'); class GerritClient { requestDetails = [ 'SUBMITTABLE', //include the submittable field in ChangeInfo, which can be used to tell if the change is reviewed and ready for submit. 'CHECK', // include potential consistency problems with the change (not related to labels) 'MESSAGES', 'DETAILED_ACCOUNTS', 'LABELS', 'CURRENT_ACTIONS', //to check if current_revision can be "rebased" 'CURRENT_REVISION', //get RevisionInfo::ref to fetch 'CURRENT_COMMIT', // to get the commit message ]; gerritHttp = new gerrit_1.GerritHttp(); async getRepos() { const res = await this.gerritHttp.getJsonUnchecked('a/projects/?type=CODE&state=ACTIVE', {}); return Object.keys(res.body); } async getProjectInfo(repository) { const projectInfo = await this.gerritHttp.getJsonUnchecked(`a/projects/${encodeURIComponent(repository)}`); if (projectInfo.body.state !== 'ACTIVE') { throw new Error(error_messages_1.REPOSITORY_ARCHIVED); } return projectInfo.body; } async getBranchInfo(repository) { const branchInfo = await this.gerritHttp.getJsonUnchecked(`a/projects/${encodeURIComponent(repository)}/branches/HEAD`); return branchInfo.body; } async findChanges(repository, findPRConfig, refreshCache) { const opts = {}; /* v8 ignore start: temporary code */ // TODO: should refresh the cache rather than just ignore it if (refreshCache) { opts.memCache = false; } else { opts.cacheProvider = memory_http_cache_provider_1.memCacheProvider; } /* v8 ignore stop */ const filters = GerritClient.buildSearchFilters(repository, findPRConfig); const changes = await this.gerritHttp.getJsonUnchecked(`a/changes/?q=` + filters.join('+') + this.requestDetails.map((det) => `&o=${det}`).join(''), opts); logger_1.logger.trace(`findChanges(${filters.join(', ')}) => ${changes.body.length}`); return changes.body; } async getChange(changeNumber) { const changes = await this.gerritHttp.getJsonUnchecked(`a/changes/${changeNumber}?` + this.requestDetails.map((det) => `o=${det}`).join('&')); return changes.body; } async getMergeableInfo(change) { const mergeable = await this.gerritHttp.getJsonUnchecked(`a/changes/${change._number}/revisions/current/mergeable`); return mergeable.body; } async abandonChange(changeNumber) { await this.gerritHttp.postJson(`a/changes/${changeNumber}/abandon`); } async submitChange(changeNumber) { const change = await this.gerritHttp.postJson(`a/changes/${changeNumber}/submit`); return change.body; } async getMessages(changeNumber) { const messages = await this.gerritHttp.getJsonUnchecked(`a/changes/${changeNumber}/messages`, { memCache: false }); return messages.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) { const messages = await this.getMessages(changeNumber); return messages.some((existingMsg) => (msgType === undefined || 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 addReviewers(changeNumber, reviewers) { await this.gerritHttp.postJson(`a/changes/${changeNumber}/revisions/current/review`, { body: { reviewers: reviewers.map((r) => ({ reviewer: r })), notify: 'OWNER_REVIEWERS', // Avoids notifying cc's }, }); } async addAssignee(changeNumber, assignee) { await this.gerritHttp.putJson( // TODO: refactor this as this API removed in Gerrit 3.8 `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 approveChange(changeId) { const isApproved = await this.checkIfApproved(changeId); if (!isApproved) { await this.setLabel(changeId, 'Code-Review', +2); } } async checkIfApproved(changeId) { const change = await exports.client.getChange(changeId); const reviewLabels = change?.labels?.['Code-Review']; return reviewLabels === undefined || reviewLabels.approved !== undefined; } wasApprovedBy(change, username) { return (change.labels?.['Code-Review'].approved && change.labels['Code-Review'].approved.username === username); } normalizeMessage(message) { //the last \n was removed from gerrit after the comment was added... return message.substring(0, 0x4000).trim(); } static buildSearchFilters(repository, searchConfig) { const filterState = (0, utils_1.mapPrStateToGerritFilter)(searchConfig.state); const filters = ['owner:self', 'project:' + repository, filterState]; if (searchConfig.branchName) { filters.push(...[ '(', `footer:Renovate-Branch=${searchConfig.branchName}`, // for backwards compatibility 'OR', `hashtag:sourceBranch-${searchConfig.branchName}`, ')', ]); } if (searchConfig.targetBranch) { filters.push(`branch:${searchConfig.targetBranch}`); } if (searchConfig.label) { filters.push(`label:Code-Review=${searchConfig.label}`); } if (searchConfig.prTitle) { // escaping support in Gerrit is not great, so we need to remove quotes // special characters are ignored anyway in the search so it does not create any issues filters.push(`message:${encodeURIComponent('"' + searchConfig.prTitle.replace(QUOTES_REGEX, '') + '"')}`); } return filters; } } exports.client = new GerritClient(); //# sourceMappingURL=client.js.map