renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
179 lines • 7.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GerritScm = void 0;
exports.configureScm = configureScm;
const tslib_1 = require("tslib");
const crypto_1 = require("crypto");
const logger_1 = require("../../../logger");
const git = tslib_1.__importStar(require("../../../util/git"));
const hash_1 = require("../../../util/hash");
const default_scm_1 = require("../default-scm");
const client_1 = require("./client");
let repository;
let username;
function configureScm(repo, login) {
repository = repo;
username = login;
}
class GerritScm extends default_scm_1.DefaultGitScm {
async branchExists(branchName) {
const searchConfig = {
state: 'open',
branchName,
limit: 1,
refreshCache: true,
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
return true;
}
return git.branchExists(branchName);
}
async getBranchCommit(branchName) {
const searchConfig = {
state: 'open',
branchName,
limit: 1,
refreshCache: true,
requestDetails: ['CURRENT_REVISION'],
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
return change.current_revision;
}
return git.getBranchCommit(branchName);
}
async isBranchBehindBase(branchName, baseBranch) {
const searchConfig = {
state: 'open',
branchName,
targetBranch: baseBranch,
limit: 1,
refreshCache: true,
requestDetails: ['CURRENT_REVISION', 'CURRENT_ACTIONS'],
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
const currentRevision = change.revisions[change.current_revision];
return currentRevision.actions.rebase.enabled === true;
}
return true;
}
async isBranchConflicted(baseBranch, branch) {
const searchConfig = {
state: 'open',
branchName: branch,
targetBranch: baseBranch,
limit: 1,
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
const mergeInfo = await client_1.client.getMergeableInfo(change);
return !mergeInfo.mergeable;
}
else {
logger_1.logger.warn({ branch, baseBranch }, 'There is no open change with this branch');
return true;
}
}
async isBranchModified(branchName, baseBranch) {
const searchConfig = {
state: 'open',
branchName,
targetBranch: baseBranch,
limit: 1,
refreshCache: true,
requestDetails: ['CURRENT_REVISION', 'DETAILED_ACCOUNTS'],
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
const currentRevision = change.revisions[change.current_revision];
return currentRevision.uploader.username !== username;
}
return false;
}
async commitAndPush(commit) {
logger_1.logger.debug(`commitAndPush(${commit.branchName})`);
const searchConfig = {
state: 'open',
branchName: commit.branchName,
targetBranch: commit.baseBranch,
limit: 1,
refreshCache: true,
requestDetails: ['CURRENT_REVISION'],
};
const existingChange = (await client_1.client.findChanges(repository, searchConfig)).pop();
let hasChanges = true;
const message = typeof commit.message === 'string' ? [commit.message] : commit.message;
// In Gerrit, the change subject/title is the first line of the commit message
if (commit.prTitle) {
const firstMessageLines = message[0].split('\n');
firstMessageLines[0] = commit.prTitle;
message[0] = firstMessageLines.join('\n');
}
const changeId = existingChange?.change_id ?? generateChangeId();
commit.message = [
...message,
`Renovate-Branch: ${commit.branchName}\nChange-Id: ${changeId}`,
];
const commitResult = await git.prepareCommit({ ...commit, force: true });
if (commitResult) {
const { commitSha } = commitResult;
if (existingChange) {
const currentRevision = existingChange.revisions[existingChange.current_revision];
const fetchRefSpec = currentRevision.ref;
await git.fetchRevSpec(fetchRefSpec); // fetch current ChangeSet for git diff
hasChanges = await git.hasDiff('HEAD', 'FETCH_HEAD'); // avoid pushing empty patch sets
}
if (hasChanges || commit.force) {
const pushOptions = ['notify=NONE'];
if (commit.autoApprove) {
pushOptions.push('label=Code-Review+2');
}
if (commit.labels) {
for (const label of commit.labels) {
pushOptions.push(`hashtag=${label}`);
}
}
const pushResult = await git.pushCommit({
sourceRef: commit.branchName,
targetRef: `refs/for/${commit.baseBranch}`,
files: commit.files,
pushOptions,
});
if (pushResult) {
return commitSha;
}
}
}
return null; // empty commit, no changes in this Gerrit Change
}
deleteBranch(branchName) {
return Promise.resolve();
}
async mergeToLocal(branchName) {
const searchConfig = {
state: 'open',
branchName,
limit: 1,
refreshCache: true,
requestDetails: ['CURRENT_REVISION'],
};
const change = (await client_1.client.findChanges(repository, searchConfig)).pop();
if (change) {
const currentRevision = change.revisions[change.current_revision];
return super.mergeToLocal(currentRevision.ref);
}
return super.mergeToLocal(branchName);
}
}
exports.GerritScm = GerritScm;
/**
* This function should generate a Gerrit Change-ID analogous to the commit hook. We avoid the commit hook cause of security concerns.
* random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) prefixed with an 'I'.
* TODO: Gerrit don't accept longer Change-IDs (sha256), but what happens with this https://git-scm.com/docs/hash-function-transition/ ?
*/
function generateChangeId() {
return 'I' + (0, hash_1.hash)((0, crypto_1.randomUUID)(), 'sha1');
}
//# sourceMappingURL=scm.js.map