mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 02:00:10 +00:00
9d74625d93
* build(deps): update dependency prettier to v3.9.6 | datasource | package | from | to | | ---------- | -------- | ----- | ----- | | npm | prettier | 3.8.1 | 3.9.6 | * chore: prettier fixes --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Kriese <michael.kriese@mend.io>
342 lines
8.4 KiB
TypeScript
342 lines
8.4 KiB
TypeScript
import { GlobalConfig } from '../../../config/global.ts';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import type { BranchStatus } from '../../../types/index.ts';
|
|
import { coerceArray } from '../../../util/array.ts';
|
|
import * as git from '../../../util/git/index.ts';
|
|
import { getBaseUrl, setBaseUrl } from '../../../util/http/scm-manager.ts';
|
|
import { sanitize } from '../../../util/sanitize.ts';
|
|
import { ensureTrailingSlash } from '../../../util/url.ts';
|
|
import type {
|
|
BranchStatusConfig,
|
|
CreatePRConfig,
|
|
EnsureCommentConfig,
|
|
EnsureCommentRemovalConfigByContent,
|
|
EnsureCommentRemovalConfigByTopic,
|
|
EnsureIssueConfig,
|
|
FindPRConfig,
|
|
Issue,
|
|
MergePRConfig,
|
|
PlatformParams,
|
|
PlatformResult,
|
|
Pr,
|
|
RepoParams,
|
|
RepoResult,
|
|
UpdatePrConfig,
|
|
} from '../types.ts';
|
|
import { repoFingerprint } from '../util.ts';
|
|
import { smartTruncate } from '../utils/pr-body.ts';
|
|
import { mapPrFromScmToRenovate } from './mapper.ts';
|
|
import {
|
|
createScmPr,
|
|
getAllRepoPrs,
|
|
getAllRepos,
|
|
getCurrentUser,
|
|
getDefaultBranch,
|
|
getRepo,
|
|
getRepoPr,
|
|
updateScmPr,
|
|
} from './scm-manager-helper.ts';
|
|
import { getRepoUrl, mapPrState, matchPrState, smartLinks } from './utils.ts';
|
|
|
|
interface SCMMRepoConfig {
|
|
repository: string;
|
|
prList: Pr[] | null;
|
|
defaultBranch: string;
|
|
ignorePrAuthor: boolean;
|
|
}
|
|
|
|
export const id = 'scm-manager';
|
|
export const experimental = true;
|
|
|
|
let config: SCMMRepoConfig = {} as any;
|
|
|
|
export async function initPlatform({
|
|
endpoint,
|
|
token,
|
|
}: PlatformParams): Promise<PlatformResult> {
|
|
if (!endpoint) {
|
|
throw new Error('Init: SCM-Manager endpoint not configured');
|
|
}
|
|
|
|
if (!token) {
|
|
throw new Error('Init: SCM-Manager API token not configured');
|
|
}
|
|
|
|
const baseUrl = `${ensureTrailingSlash(endpoint)}api/v2`;
|
|
setBaseUrl(baseUrl);
|
|
|
|
try {
|
|
const me = await getCurrentUser(token);
|
|
const gitAuthor = `${me.displayName} <${me.mail}>`;
|
|
const result = { endpoint: baseUrl, gitAuthor };
|
|
|
|
logger.debug({ result }, 'Platform result');
|
|
|
|
return result;
|
|
} catch (err) {
|
|
logger.debug(
|
|
{ err },
|
|
'Init: Error authenticating with SCM-Manager. Check your token',
|
|
);
|
|
throw new Error('Init: Authentication failure');
|
|
}
|
|
}
|
|
|
|
export async function initRepo({
|
|
repository,
|
|
gitUrl,
|
|
}: RepoParams): Promise<RepoResult> {
|
|
const repo = await getRepo(repository);
|
|
const defaultBranch = await getDefaultBranch(repo);
|
|
const url = getRepoUrl(repo, gitUrl, getBaseUrl());
|
|
|
|
config = {} as any;
|
|
config.repository = repository;
|
|
config.defaultBranch = defaultBranch;
|
|
config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');
|
|
|
|
await git.initRepo({
|
|
...config,
|
|
url,
|
|
});
|
|
|
|
// Reset cached resources
|
|
invalidatePrCache();
|
|
|
|
const result = {
|
|
defaultBranch: config.defaultBranch,
|
|
isFork: false,
|
|
repoFingerprint: repoFingerprint(config.repository, getBaseUrl()),
|
|
};
|
|
|
|
logger.debug({ result }, `Repo initialized`);
|
|
|
|
return result;
|
|
}
|
|
|
|
export async function getRepos(): Promise<string[]> {
|
|
const repos = (await getAllRepos()).filter((repo) => repo.type === 'git');
|
|
return repos.map((repo) => `${repo.namespace}/${repo.name}`);
|
|
}
|
|
|
|
export async function getBranchPr(branchName: string): Promise<Pr | null> {
|
|
return await findPr({ branchName, state: 'open' });
|
|
}
|
|
|
|
export async function findPr({
|
|
branchName,
|
|
prTitle,
|
|
state = 'all',
|
|
}: FindPRConfig): Promise<Pr | null> {
|
|
const inProgressPrs = await getPrList();
|
|
const result = inProgressPrs.find(
|
|
(pr) =>
|
|
branchName === pr.sourceBranch &&
|
|
(!prTitle || prTitle === pr.title) &&
|
|
matchPrState(pr, state),
|
|
);
|
|
|
|
if (result) {
|
|
logger.debug({ result }, `Found PR`);
|
|
return result;
|
|
}
|
|
|
|
logger.debug(
|
|
`Could not find PR with source branch ${branchName} and title ${
|
|
prTitle ?? ''
|
|
} and state ${state}`,
|
|
);
|
|
|
|
return null;
|
|
}
|
|
|
|
export async function getPr(number: number): Promise<Pr | null> {
|
|
const inProgressPrs = await getPrList();
|
|
const cachedPr = inProgressPrs.find((pr) => pr.number === number);
|
|
|
|
if (cachedPr) {
|
|
logger.debug('Returning from cached PRs');
|
|
return cachedPr;
|
|
}
|
|
|
|
try {
|
|
const result = await getRepoPr(config.repository, number);
|
|
logger.debug('Returning PR from API');
|
|
return mapPrFromScmToRenovate(result);
|
|
} catch (err) {
|
|
logger.error({ err, number }, 'Can not find a PR with the given id');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function getPrList(): Promise<Pr[]> {
|
|
if (config.prList === null) {
|
|
try {
|
|
config.prList = (
|
|
await getAllRepoPrs(config.repository, config.ignorePrAuthor)
|
|
).map((pr) => mapPrFromScmToRenovate(pr));
|
|
} catch (error) {
|
|
logger.error(error);
|
|
}
|
|
}
|
|
|
|
return coerceArray(config.prList);
|
|
}
|
|
|
|
export async function createPr({
|
|
sourceBranch,
|
|
targetBranch,
|
|
prTitle,
|
|
prBody,
|
|
draftPR,
|
|
}: CreatePRConfig): Promise<Pr> {
|
|
const createdPr = await createScmPr(config.repository, {
|
|
source: sourceBranch,
|
|
target: targetBranch,
|
|
title: prTitle,
|
|
description: sanitize(prBody),
|
|
status: draftPR ? 'DRAFT' : 'OPEN',
|
|
});
|
|
|
|
logger.debug(
|
|
`PR created with title '${createdPr.title}' from source '${createdPr.source}' to target '${createdPr.target}'`,
|
|
);
|
|
|
|
return mapPrFromScmToRenovate(createdPr);
|
|
}
|
|
|
|
export async function updatePr({
|
|
number,
|
|
prTitle,
|
|
prBody,
|
|
state,
|
|
targetBranch,
|
|
}: UpdatePrConfig): Promise<void> {
|
|
await updateScmPr(config.repository, number, {
|
|
title: prTitle,
|
|
description: sanitize(prBody) ?? undefined,
|
|
target: targetBranch,
|
|
status: mapPrState(state),
|
|
});
|
|
|
|
logger.debug(`Updated PR #${number} with title ${prTitle}`);
|
|
}
|
|
|
|
export function mergePr(_config: MergePRConfig): Promise<boolean> {
|
|
logger.debug('Not implemented mergePr');
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
export function getBranchStatus(
|
|
_branchName: string,
|
|
_internalChecksAsSuccess: boolean,
|
|
): Promise<BranchStatus> {
|
|
logger.debug('Not implemented getBranchStatus');
|
|
return Promise.resolve('red');
|
|
}
|
|
|
|
export function setBranchStatus(
|
|
_branchStatusConfig: BranchStatusConfig,
|
|
): Promise<void> {
|
|
logger.debug('Not implemented setBranchStatus');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function getBranchStatusCheck(
|
|
_branchName: string,
|
|
_context: string | null | undefined,
|
|
): Promise<BranchStatus | null> {
|
|
logger.debug('Not implemented setBranchStatus');
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
export function addReviewers(
|
|
_number: number,
|
|
_reviewers: string[],
|
|
): Promise<void> {
|
|
logger.debug('Not implemented addReviewers');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function addAssignees(
|
|
_number: number,
|
|
_assignees: string[],
|
|
): Promise<void> {
|
|
logger.debug('Not implemented addAssignees');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function deleteLabel(_number: number, _label: string): Promise<void> {
|
|
logger.debug('Not implemented deleteLabel');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function getIssueList(): Promise<Issue[]> {
|
|
logger.debug('Not implemented getIssueList');
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
export function findIssue(_title: string): Promise<Issue | null> {
|
|
logger.debug('Not implemented findIssue');
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
export function ensureIssue(
|
|
_config: EnsureIssueConfig,
|
|
): Promise<'updated' | 'created' | null> {
|
|
logger.debug('Not implemented ensureIssue');
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
export function ensureIssueClosing(_title: string): Promise<void> {
|
|
logger.debug('Not implemented ensureIssueClosing');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function ensureComment(_config: EnsureCommentConfig): Promise<boolean> {
|
|
logger.debug('Not implemented ensureComment');
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
export function ensureCommentRemoval(
|
|
_ensureCommentRemoval:
|
|
EnsureCommentRemovalConfigByTopic | EnsureCommentRemovalConfigByContent,
|
|
): Promise<void> {
|
|
logger.debug('Not implemented ensureCommentRemoval');
|
|
return Promise.resolve();
|
|
}
|
|
|
|
export function massageMarkdown(prBody: string): string {
|
|
return smartTruncate(smartLinks(prBody), maxBodyLength());
|
|
}
|
|
|
|
export function getRepoForceRebase(): Promise<boolean> {
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
export function getRawFile(
|
|
_fileName: string,
|
|
_repoName?: string,
|
|
_branchOrTag?: string,
|
|
): Promise<string | null> {
|
|
logger.debug('Not implemented getRawFile');
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
export function getJsonFile(
|
|
_fileName: string,
|
|
_repoName?: string,
|
|
_branchOrTag?: string,
|
|
): Promise<any> {
|
|
logger.debug('Not implemented getJsonFile');
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
export function maxBodyLength(): number {
|
|
return 200000;
|
|
}
|
|
|
|
export function invalidatePrCache(): void {
|
|
config.prList = null;
|
|
}
|