feat(bitbucket-server): convert to typescript (#3756)
This commit is contained in:
Родитель
154f776ceb
Коммит
cc52c20533
|
@ -32,6 +32,13 @@ module.exports = {
|
|||
'promise/no-promise-in-callback': 'warn',
|
||||
'promise/no-callback-in-promise': 'warn',
|
||||
'promise/avoid-new': 'warn',
|
||||
|
||||
'@typescript-eslint/explicit-member-accessibility': 0,
|
||||
'@typescript-eslint/explicit-function-return-type': 0,
|
||||
'@typescript-eslint/interface-name-prefix': 0,
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/no-non-null-assertion': 0,
|
||||
'no-underscore-dangle': 0,
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
const got = require('got');
|
||||
const URL = require('url');
|
||||
const hostRules = require('../../util/host-rules');
|
||||
import got from 'got';
|
||||
import URL from 'url';
|
||||
import * as hostRules from '../../util/host-rules';
|
||||
import { IGotApiOptions, IGotApi } from '../common';
|
||||
|
||||
let cache = {};
|
||||
let cache: Renovate.IDict<got.Response<any>> = {};
|
||||
|
||||
const platform = 'bitbucket-server';
|
||||
let endpoint;
|
||||
let endpoint: string;
|
||||
|
||||
async function get(path, options) {
|
||||
async function get(path: string, options: IGotApiOptions & got.GotJSONOptions) {
|
||||
const host = URL.parse(path).host || URL.parse(endpoint).host;
|
||||
const opts = {
|
||||
const opts: IGotApiOptions &
|
||||
hostRules.IPlatformConfig &
|
||||
got.GotJSONOptions = {
|
||||
// TODO: Move to configurable host rules, or use utils/got
|
||||
timeout: 60 * 1000,
|
||||
json: true,
|
||||
|
@ -18,7 +21,9 @@ async function get(path, options) {
|
|||
...options,
|
||||
};
|
||||
const url = URL.resolve(endpoint, path);
|
||||
const method = (opts.method || 'get').toLowerCase();
|
||||
const method = (
|
||||
opts.method || /* istanbul ignore next */ 'get'
|
||||
).toLowerCase();
|
||||
const useCache = opts.useCache;
|
||||
if (method === 'get' && useCache !== false && cache[path]) {
|
||||
logger.trace({ path }, 'Returning cached result');
|
||||
|
@ -27,7 +32,10 @@ async function get(path, options) {
|
|||
opts.headers = {
|
||||
'user-agent': 'https://github.com/renovatebot/renovate',
|
||||
'X-Atlassian-Token': 'no-check',
|
||||
authorization: opts.token ? `Basic ${opts.token}` : undefined,
|
||||
|
||||
authorization: opts.token
|
||||
? /* istanbul ignore next */ `Basic ${opts.token}`
|
||||
: undefined,
|
||||
...opts.headers,
|
||||
};
|
||||
|
||||
|
@ -41,17 +49,19 @@ async function get(path, options) {
|
|||
|
||||
const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete'];
|
||||
|
||||
export const api: IGotApi = {} as any;
|
||||
|
||||
for (const x of helpers) {
|
||||
get[x] = (url, opts) =>
|
||||
(api as any)[x] = (url: string, opts: any) =>
|
||||
get(url, Object.assign({}, opts, { method: x.toUpperCase() }));
|
||||
}
|
||||
|
||||
get.reset = function reset() {
|
||||
api.reset = function reset() {
|
||||
cache = {};
|
||||
};
|
||||
|
||||
get.setEndpoint = e => {
|
||||
api.setEndpoint = (e: string) => {
|
||||
endpoint = e;
|
||||
};
|
||||
|
||||
module.exports = get;
|
||||
export default api;
|
|
@ -1,71 +1,42 @@
|
|||
const url = require('url');
|
||||
const delay = require('delay');
|
||||
import url from 'url';
|
||||
import delay from 'delay';
|
||||
|
||||
const api = require('./bb-got-wrapper');
|
||||
const utils = require('./utils');
|
||||
const hostRules = require('../../util/host-rules');
|
||||
const GitStorage = require('../git/storage');
|
||||
import api from './bb-got-wrapper';
|
||||
import * as utils from './utils';
|
||||
import * as hostRules from '../../util/host-rules';
|
||||
import GitStorage from '../git/storage';
|
||||
|
||||
const platform = 'bitbucket-server';
|
||||
|
||||
let config = {};
|
||||
interface BbsConfig {
|
||||
baseBranch: string;
|
||||
bbUseDefaultReviewers: boolean;
|
||||
defaultBranch: string;
|
||||
fileList: any[];
|
||||
mergeMethod: string;
|
||||
owner: string;
|
||||
prList: any[];
|
||||
projectKey: string;
|
||||
repository: string;
|
||||
repositorySlug: string;
|
||||
storage: GitStorage;
|
||||
}
|
||||
|
||||
const defaults = {
|
||||
let config: BbsConfig = {} as any;
|
||||
|
||||
const defaults: any = {
|
||||
platform: 'bitbucket-server',
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initPlatform,
|
||||
getRepos,
|
||||
cleanRepo,
|
||||
initRepo,
|
||||
getRepoStatus,
|
||||
getRepoForceRebase,
|
||||
setBaseBranch,
|
||||
setBranchPrefix,
|
||||
// Search
|
||||
getFileList,
|
||||
// Branch
|
||||
branchExists,
|
||||
getAllRenovateBranches,
|
||||
isBranchStale,
|
||||
getBranchPr,
|
||||
getBranchStatus,
|
||||
getBranchStatusCheck,
|
||||
setBranchStatus,
|
||||
deleteBranch,
|
||||
mergeBranch,
|
||||
getBranchLastCommitTime,
|
||||
// issue
|
||||
findIssue,
|
||||
ensureIssue,
|
||||
ensureIssueClosing,
|
||||
addAssignees,
|
||||
addReviewers,
|
||||
deleteLabel,
|
||||
getIssueList,
|
||||
// Comments
|
||||
ensureComment,
|
||||
ensureCommentRemoval,
|
||||
// PR
|
||||
getPrList,
|
||||
findPr,
|
||||
createPr,
|
||||
getPr,
|
||||
getPrFiles,
|
||||
updatePr,
|
||||
mergePr,
|
||||
getPrBody,
|
||||
// file
|
||||
commitFilesToBranch,
|
||||
getFile,
|
||||
// commits
|
||||
getCommitMessages,
|
||||
// vulnerability alerts
|
||||
getVulnerabilityAlerts,
|
||||
};
|
||||
|
||||
function initPlatform({ endpoint, username, password }) {
|
||||
export function initPlatform({
|
||||
endpoint,
|
||||
username,
|
||||
password,
|
||||
}: {
|
||||
endpoint: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}) {
|
||||
if (!endpoint) {
|
||||
throw new Error('Init: You must configure a Bitbucket Server endpoint');
|
||||
}
|
||||
|
@ -84,13 +55,16 @@ function initPlatform({ endpoint, username, password }) {
|
|||
}
|
||||
|
||||
// Get all repositories that the user has access to
|
||||
async function getRepos() {
|
||||
export async function getRepos() {
|
||||
logger.info('Autodiscovering Bitbucket Server repositories');
|
||||
try {
|
||||
const repos = await utils.accumulateValues(
|
||||
`./rest/api/1.0/repos?permission=REPO_WRITE&state=AVAILABLE`
|
||||
);
|
||||
const result = repos.map(r => `${r.project.key.toLowerCase()}/${r.slug}`);
|
||||
const result = repos.map(
|
||||
(r: { project: { key: string }; slug: string }) =>
|
||||
`${r.project.key.toLowerCase()}/${r.slug}`
|
||||
);
|
||||
logger.debug({ result }, 'result of getRepos()');
|
||||
return result;
|
||||
} catch (err) /* istanbul ignore next */ {
|
||||
|
@ -99,23 +73,30 @@ async function getRepos() {
|
|||
}
|
||||
}
|
||||
|
||||
function cleanRepo() {
|
||||
export function cleanRepo() {
|
||||
logger.debug(`cleanRepo()`);
|
||||
if (config.storage) {
|
||||
config.storage.cleanRepo();
|
||||
}
|
||||
api.reset();
|
||||
config = {};
|
||||
config = {} as any;
|
||||
}
|
||||
|
||||
// Initialize GitLab by getting base branch
|
||||
async function initRepo({
|
||||
export async function initRepo({
|
||||
repository,
|
||||
endpoint,
|
||||
gitPrivateKey,
|
||||
gitFs,
|
||||
localDir,
|
||||
bbUseDefaultReviewers,
|
||||
}: {
|
||||
repository: string;
|
||||
endpoint: string;
|
||||
gitPrivateKey?: string;
|
||||
gitFs?: string;
|
||||
localDir: string;
|
||||
bbUseDefaultReviewers?: boolean;
|
||||
}) {
|
||||
logger.debug(
|
||||
`initRepo("${JSON.stringify(
|
||||
|
@ -128,7 +109,7 @@ async function initRepo({
|
|||
api.reset();
|
||||
|
||||
const [projectKey, repositorySlug] = repository.split('/');
|
||||
config = { projectKey, repositorySlug, gitPrivateKey };
|
||||
config = { projectKey, repositorySlug, gitPrivateKey, repository } as any;
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (bbUseDefaultReviewers !== false) {
|
||||
|
@ -137,11 +118,13 @@ async function initRepo({
|
|||
}
|
||||
|
||||
// Always gitFs
|
||||
const { host, pathname } = url.parse(opts.endpoint);
|
||||
const { host, pathname } = url.parse(opts!.endpoint!);
|
||||
const gitUrl = GitStorage.getUrl({
|
||||
gitFs: opts.endpoint.split(':')[0],
|
||||
auth: `${opts.username}:${opts.password}`,
|
||||
host: `${host}${pathname}${pathname.endsWith('/') ? '' : '/'}scm`,
|
||||
gitFs: opts!.endpoint!.split(':')[0] as any,
|
||||
auth: `${opts!.username}:${opts!.password}`,
|
||||
host: `${host}${pathname}${
|
||||
pathname!.endsWith('/') ? '' : /* istanbul ignore next */ '/'
|
||||
}scm`,
|
||||
repository,
|
||||
});
|
||||
|
||||
|
@ -152,7 +135,7 @@ async function initRepo({
|
|||
url: gitUrl,
|
||||
});
|
||||
|
||||
const platformConfig = {};
|
||||
const platformConfig: any = {};
|
||||
|
||||
try {
|
||||
const info = (await api.get(
|
||||
|
@ -189,7 +172,7 @@ async function initRepo({
|
|||
return platformConfig;
|
||||
}
|
||||
|
||||
function getRepoForceRebase() {
|
||||
export function getRepoForceRebase() {
|
||||
logger.debug(`getRepoForceRebase()`);
|
||||
// TODO if applicable
|
||||
// This function should return true only if the user has enabled a setting on the repo that enforces PRs to be kept up to date with master
|
||||
|
@ -198,20 +181,20 @@ function getRepoForceRebase() {
|
|||
return false;
|
||||
}
|
||||
|
||||
async function setBaseBranch(branchName = config.defaultBranch) {
|
||||
export async function setBaseBranch(branchName: string = config.defaultBranch) {
|
||||
config.baseBranch = branchName;
|
||||
await config.storage.setBaseBranch(branchName);
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
function setBranchPrefix(branchPrefix) {
|
||||
export function setBranchPrefix(branchPrefix: string) {
|
||||
return config.storage.setBranchPrefix(branchPrefix);
|
||||
}
|
||||
|
||||
// Search
|
||||
|
||||
// Get full file list
|
||||
function getFileList(branchName = config.baseBranch) {
|
||||
export function getFileList(branchName: string = config.baseBranch) {
|
||||
logger.debug(`getFileList(${branchName})`);
|
||||
return config.storage.getFileList(branchName);
|
||||
}
|
||||
|
@ -219,33 +202,33 @@ function getFileList(branchName = config.baseBranch) {
|
|||
// Branch
|
||||
|
||||
// Returns true if branch exists, otherwise false
|
||||
function branchExists(branchName) {
|
||||
export function branchExists(branchName: string) {
|
||||
logger.debug(`branchExists(${branchName})`);
|
||||
return config.storage.branchExists(branchName);
|
||||
}
|
||||
|
||||
// Returns the Pull Request for a branch. Null if not exists.
|
||||
async function getBranchPr(branchName, refreshCache) {
|
||||
export async function getBranchPr(branchName: string, refreshCache?: boolean) {
|
||||
logger.debug(`getBranchPr(${branchName})`);
|
||||
const existingPr = await findPr(branchName, null, 'open');
|
||||
const existingPr = await findPr(branchName, undefined, 'open');
|
||||
return existingPr ? getPr(existingPr.number, refreshCache) : null;
|
||||
}
|
||||
|
||||
function getAllRenovateBranches(branchPrefix) {
|
||||
export function getAllRenovateBranches(branchPrefix: string) {
|
||||
logger.debug('getAllRenovateBranches');
|
||||
return config.storage.getAllRenovateBranches(branchPrefix);
|
||||
}
|
||||
|
||||
function isBranchStale(branchName) {
|
||||
export function isBranchStale(branchName: string) {
|
||||
logger.debug(`isBranchStale(${branchName})`);
|
||||
return config.storage.isBranchStale(branchName);
|
||||
}
|
||||
|
||||
async function commitFilesToBranch(
|
||||
branchName,
|
||||
files,
|
||||
message,
|
||||
parentBranch = config.baseBranch
|
||||
export async function commitFilesToBranch(
|
||||
branchName: string,
|
||||
files: any[],
|
||||
message: string,
|
||||
parentBranch: string = config.baseBranch
|
||||
) {
|
||||
logger.debug(
|
||||
`commitFilesToBranch(${JSON.stringify(
|
||||
|
@ -267,12 +250,12 @@ async function commitFilesToBranch(
|
|||
await getBranchPr(branchName, true);
|
||||
}
|
||||
|
||||
function getFile(filePath, branchName) {
|
||||
export function getFile(filePath: string, branchName: string) {
|
||||
logger.debug(`getFile(${filePath}, ${branchName})`);
|
||||
return config.storage.getFile(filePath, branchName);
|
||||
}
|
||||
|
||||
async function deleteBranch(branchName, closePr = false) {
|
||||
export async function deleteBranch(branchName: string, closePr = false) {
|
||||
logger.debug(`deleteBranch(${branchName}, closePr=${closePr})`);
|
||||
// TODO: coverage
|
||||
// istanbul ignore next
|
||||
|
@ -292,25 +275,28 @@ async function deleteBranch(branchName, closePr = false) {
|
|||
return config.storage.deleteBranch(branchName);
|
||||
}
|
||||
|
||||
function mergeBranch(branchName) {
|
||||
export function mergeBranch(branchName: string) {
|
||||
logger.debug(`mergeBranch(${branchName})`);
|
||||
return config.storage.mergeBranch(branchName);
|
||||
}
|
||||
|
||||
function getBranchLastCommitTime(branchName) {
|
||||
export function getBranchLastCommitTime(branchName: string) {
|
||||
logger.debug(`getBranchLastCommitTime(${branchName})`);
|
||||
return config.storage.getBranchLastCommitTime(branchName);
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
function getRepoStatus() {
|
||||
export function getRepoStatus() {
|
||||
return config.storage.getRepoStatus();
|
||||
}
|
||||
|
||||
// Returns the combined status for a branch.
|
||||
// umbrella for status checks
|
||||
// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-build-rest.html#idp2
|
||||
async function getBranchStatus(branchName, requiredStatusChecks) {
|
||||
export async function getBranchStatus(
|
||||
branchName: string,
|
||||
requiredStatusChecks?: string[] | boolean | null
|
||||
) {
|
||||
logger.debug(
|
||||
`getBranchStatus(${branchName}, requiredStatusChecks=${!!requiredStatusChecks})`
|
||||
);
|
||||
|
@ -344,7 +330,10 @@ async function getBranchStatus(branchName, requiredStatusChecks) {
|
|||
}
|
||||
|
||||
// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-build-rest.html#idp2
|
||||
async function getBranchStatusCheck(branchName, context) {
|
||||
export async function getBranchStatusCheck(
|
||||
branchName: string,
|
||||
context: string
|
||||
) {
|
||||
logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);
|
||||
|
||||
const branchCommit = await config.storage.getBranchCommit(branchName);
|
||||
|
@ -373,12 +362,12 @@ async function getBranchStatusCheck(branchName, context) {
|
|||
return null;
|
||||
}
|
||||
|
||||
async function setBranchStatus(
|
||||
branchName,
|
||||
context,
|
||||
description,
|
||||
state,
|
||||
targetUrl
|
||||
export async function setBranchStatus(
|
||||
branchName: string,
|
||||
context: string,
|
||||
description: string,
|
||||
state: string | null,
|
||||
targetUrl?: string
|
||||
) {
|
||||
logger.debug(`setBranchStatus(${branchName})`);
|
||||
|
||||
|
@ -391,7 +380,7 @@ async function setBranchStatus(
|
|||
const branchCommit = await config.storage.getBranchCommit(branchName);
|
||||
|
||||
try {
|
||||
const body = {
|
||||
const body: any = {
|
||||
key: context,
|
||||
description,
|
||||
url: targetUrl || 'https://renovatebot.com',
|
||||
|
@ -427,7 +416,7 @@ async function setBranchStatus(
|
|||
// }
|
||||
|
||||
// istanbul ignore next
|
||||
function findIssue(title) {
|
||||
export function findIssue(title: string) {
|
||||
logger.debug(`findIssue(${title})`);
|
||||
// TODO: Needs implementation
|
||||
// This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
|
||||
|
@ -436,7 +425,7 @@ function findIssue(title) {
|
|||
}
|
||||
|
||||
// istanbul ignore next
|
||||
function ensureIssue(title, body) {
|
||||
export function ensureIssue(title: string, body: string) {
|
||||
logger.debug(`ensureIssue(${title}, body={${body}})`);
|
||||
// TODO: Needs implementation
|
||||
// This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
|
||||
|
@ -445,14 +434,14 @@ function ensureIssue(title, body) {
|
|||
}
|
||||
|
||||
// istanbul ignore next
|
||||
function getIssueList() {
|
||||
export function getIssueList() {
|
||||
logger.debug(`getIssueList()`);
|
||||
// TODO: Needs implementation
|
||||
return [];
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
function ensureIssueClosing(title) {
|
||||
export function ensureIssueClosing(title: string) {
|
||||
logger.debug(`ensureIssueClosing(${title})`);
|
||||
// TODO: Needs implementation
|
||||
// This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
|
||||
|
@ -460,14 +449,14 @@ function ensureIssueClosing(title) {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function addAssignees(iid, assignees) {
|
||||
export function addAssignees(iid: number, assignees: string[]) {
|
||||
logger.debug(`addAssignees(${iid}, ${assignees})`);
|
||||
// TODO: Needs implementation
|
||||
// Currently Renovate does "Create PR" and then "Add assignee" as a two-step process, with this being the second step.
|
||||
// BB Server doesnt support assignees
|
||||
}
|
||||
|
||||
async function addReviewers(prNo, reviewers) {
|
||||
export async function addReviewers(prNo: number, reviewers: string[]) {
|
||||
logger.debug(`Adding reviewers ${reviewers} to #${prNo}`);
|
||||
|
||||
try {
|
||||
|
@ -505,13 +494,13 @@ async function addReviewers(prNo, reviewers) {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function deleteLabel(issueNo, label) {
|
||||
export function deleteLabel(issueNo: number, label: string) {
|
||||
logger.debug(`deleteLabel(${issueNo}, ${label})`);
|
||||
// TODO: Needs implementation
|
||||
// Only used for the "request Renovate to rebase a PR using a label" feature
|
||||
}
|
||||
|
||||
async function getComments(prNo) {
|
||||
async function getComments(prNo: number) {
|
||||
// GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/activities
|
||||
let comments = await utils.accumulateValues(
|
||||
`./rest/api/1.0/projects/${config.projectKey}/repos/${
|
||||
|
@ -520,15 +509,18 @@ async function getComments(prNo) {
|
|||
);
|
||||
|
||||
comments = comments
|
||||
.filter(a => a.action === 'COMMENTED' && a.commentAction === 'ADDED')
|
||||
.map(a => a.comment);
|
||||
.filter(
|
||||
(a: { action: string; commentAction: string }) =>
|
||||
a.action === 'COMMENTED' && a.commentAction === 'ADDED'
|
||||
)
|
||||
.map((a: { comment: string }) => a.comment);
|
||||
|
||||
logger.debug(`Found ${comments.length} comments`);
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
async function addComment(prNo, text) {
|
||||
async function addComment(prNo: number, text: string) {
|
||||
// POST /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments
|
||||
await api.post(
|
||||
`./rest/api/1.0/projects/${config.projectKey}/repos/${
|
||||
|
@ -540,7 +532,7 @@ async function addComment(prNo, text) {
|
|||
);
|
||||
}
|
||||
|
||||
async function getCommentVersion(prNo, commentId) {
|
||||
async function getCommentVersion(prNo: number, commentId: number) {
|
||||
// GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
|
||||
const { version } = (await api.get(
|
||||
`./rest/api/1.0/projects/${config.projectKey}/repos/${
|
||||
|
@ -551,7 +543,7 @@ async function getCommentVersion(prNo, commentId) {
|
|||
return version;
|
||||
}
|
||||
|
||||
async function editComment(prNo, commentId, text) {
|
||||
async function editComment(prNo: number, commentId: number, text: string) {
|
||||
const version = await getCommentVersion(prNo, commentId);
|
||||
|
||||
// PUT /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
|
||||
|
@ -565,7 +557,7 @@ async function editComment(prNo, commentId, text) {
|
|||
);
|
||||
}
|
||||
|
||||
async function deleteComment(prNo, commentId) {
|
||||
async function deleteComment(prNo: number, commentId: number) {
|
||||
const version = await getCommentVersion(prNo, commentId);
|
||||
|
||||
// DELETE /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
|
||||
|
@ -576,16 +568,20 @@ async function deleteComment(prNo, commentId) {
|
|||
);
|
||||
}
|
||||
|
||||
async function ensureComment(prNo, topic, content) {
|
||||
export async function ensureComment(
|
||||
prNo: number,
|
||||
topic: string | null,
|
||||
content: string
|
||||
) {
|
||||
try {
|
||||
const comments = await getComments(prNo);
|
||||
let body;
|
||||
let commentId;
|
||||
let commentNeedsUpdating;
|
||||
let body: string;
|
||||
let commentId: number | undefined;
|
||||
let commentNeedsUpdating: boolean | undefined;
|
||||
if (topic) {
|
||||
logger.debug(`Ensuring comment "${topic}" in #${prNo}`);
|
||||
body = `### ${topic}\n\n${content}`;
|
||||
comments.forEach(comment => {
|
||||
comments.forEach((comment: { text: string; id: number }) => {
|
||||
if (comment.text.startsWith(`### ${topic}\n\n`)) {
|
||||
commentId = comment.id;
|
||||
commentNeedsUpdating = comment.text !== body;
|
||||
|
@ -594,7 +590,7 @@ async function ensureComment(prNo, topic, content) {
|
|||
} else {
|
||||
logger.debug(`Ensuring content-only comment in #${prNo}`);
|
||||
body = `${content}`;
|
||||
comments.forEach(comment => {
|
||||
comments.forEach((comment: { text: string; id: number }) => {
|
||||
if (comment.text === body) {
|
||||
commentId = comment.id;
|
||||
commentNeedsUpdating = false;
|
||||
|
@ -617,13 +613,12 @@ async function ensureComment(prNo, topic, content) {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
async function ensureCommentRemoval(prNo, topic) {
|
||||
export async function ensureCommentRemoval(prNo: number, topic: string) {
|
||||
try {
|
||||
logger.debug(`Ensuring comment "${topic}" in #${prNo} is removed`);
|
||||
const comments = await getComments(prNo);
|
||||
let commentId;
|
||||
comments.forEach(comment => {
|
||||
comments.forEach((comment: { text: string; id: any }) => {
|
||||
if (comment.text.startsWith(`### ${topic}\n\n`)) {
|
||||
commentId = comment.id;
|
||||
}
|
||||
|
@ -638,7 +633,8 @@ async function ensureCommentRemoval(prNo, topic) {
|
|||
|
||||
// TODO: coverage
|
||||
// istanbul ignore next
|
||||
async function getPrList() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export async function getPrList(_args?: any) {
|
||||
logger.debug(`getPrList()`);
|
||||
if (!config.prList) {
|
||||
const values = await utils.accumulateValues(
|
||||
|
@ -657,7 +653,7 @@ async function getPrList() {
|
|||
|
||||
// TODO: coverage
|
||||
// istanbul ignore next
|
||||
function matchesState(state, desiredState) {
|
||||
function matchesState(state: string, desiredState: string) {
|
||||
if (desiredState === 'all') {
|
||||
return true;
|
||||
}
|
||||
|
@ -669,14 +665,23 @@ function matchesState(state, desiredState) {
|
|||
|
||||
// TODO: coverage
|
||||
// istanbul ignore next
|
||||
const isRelevantPr = (branchName, prTitle, state) => p =>
|
||||
const isRelevantPr = (
|
||||
branchName: string,
|
||||
prTitle: string | null | undefined,
|
||||
state: string
|
||||
) => (p: { branchName: string; title: string; state: string }) =>
|
||||
p.branchName === branchName &&
|
||||
(!prTitle || p.title === prTitle) &&
|
||||
matchesState(p.state, state);
|
||||
|
||||
// TODO: coverage
|
||||
// istanbul ignore next
|
||||
async function findPr(branchName, prTitle, state = 'all', refreshCache) {
|
||||
export async function findPr(
|
||||
branchName: string,
|
||||
prTitle?: string,
|
||||
state = 'all',
|
||||
refreshCache?: boolean
|
||||
) {
|
||||
logger.debug(`findPr(${branchName}, "${prTitle}", "${state}")`);
|
||||
const prList = await getPrList({ refreshCache });
|
||||
const pr = prList.find(isRelevantPr(branchName, prTitle, state));
|
||||
|
@ -690,12 +695,12 @@ async function findPr(branchName, prTitle, state = 'all', refreshCache) {
|
|||
|
||||
// Pull Request
|
||||
|
||||
async function createPr(
|
||||
branchName,
|
||||
title,
|
||||
description,
|
||||
labels,
|
||||
useDefaultBranch
|
||||
export async function createPr(
|
||||
branchName: string,
|
||||
title: string,
|
||||
description: string,
|
||||
_labels?: string[] | null,
|
||||
useDefaultBranch?: boolean
|
||||
) {
|
||||
logger.debug(`createPr(${branchName}, title=${title})`);
|
||||
const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
|
||||
|
@ -716,7 +721,9 @@ async function createPr(
|
|||
}/reviewers?sourceRefId=refs/heads/${branchName}&targetRefId=refs/heads/${base}&sourceRepoId=${id}&targetRepoId=${id}`
|
||||
)).body;
|
||||
|
||||
reviewers = defReviewers.map(u => ({ user: { name: u.name } }));
|
||||
reviewers = defReviewers.map((u: { name: string }) => ({
|
||||
user: { name: u.name },
|
||||
}));
|
||||
}
|
||||
|
||||
const body = {
|
||||
|
@ -770,7 +777,7 @@ async function createPr(
|
|||
}
|
||||
|
||||
// Gets details for a PR
|
||||
async function getPr(prNo, refreshCache) {
|
||||
export async function getPr(prNo: number, refreshCache?: boolean) {
|
||||
logger.debug(`getPr(${prNo})`);
|
||||
if (!prNo) {
|
||||
return null;
|
||||
|
@ -783,10 +790,12 @@ async function getPr(prNo, refreshCache) {
|
|||
{ useCache: !refreshCache }
|
||||
);
|
||||
|
||||
const pr = {
|
||||
const pr: any = {
|
||||
displayNumber: `Pull Request #${res.body.id}`,
|
||||
...utils.prInfo(res.body),
|
||||
reviewers: res.body.reviewers.map(r => r.user.name),
|
||||
reviewers: res.body.reviewers.map(
|
||||
(r: { user: { name: any } }) => r.user.name
|
||||
),
|
||||
};
|
||||
|
||||
if (pr.state === 'open') {
|
||||
|
@ -845,7 +854,7 @@ async function getPr(prNo, refreshCache) {
|
|||
|
||||
// Return a list of all modified files in a PR
|
||||
// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html
|
||||
async function getPrFiles(prNo) {
|
||||
export async function getPrFiles(prNo: number) {
|
||||
logger.debug(`getPrFiles(${prNo})`);
|
||||
if (!prNo) {
|
||||
return [];
|
||||
|
@ -857,10 +866,14 @@ async function getPrFiles(prNo) {
|
|||
config.repositorySlug
|
||||
}/pull-requests/${prNo}/changes?withComments=false`
|
||||
);
|
||||
return values.map(f => f.path.toString);
|
||||
return values.map((f: { path: string }) => f.path.toString);
|
||||
}
|
||||
|
||||
async function updatePr(prNo, title, description) {
|
||||
export async function updatePr(
|
||||
prNo: number,
|
||||
title: string,
|
||||
description: string
|
||||
) {
|
||||
logger.debug(`updatePr(${prNo}, title=${title})`);
|
||||
|
||||
try {
|
||||
|
@ -878,7 +891,7 @@ async function updatePr(prNo, title, description) {
|
|||
title,
|
||||
description,
|
||||
version: pr.version,
|
||||
reviewers: pr.reviewers.map(name => ({ user: { name } })),
|
||||
reviewers: pr.reviewers.map((name: string) => ({ user: { name } })),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -896,7 +909,7 @@ async function updatePr(prNo, title, description) {
|
|||
}
|
||||
|
||||
// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp261
|
||||
async function mergePr(prNo, branchName) {
|
||||
export async function mergePr(prNo: number, branchName: string) {
|
||||
logger.debug(`mergePr(${prNo}, ${branchName})`);
|
||||
// Used for "automerge" feature
|
||||
try {
|
||||
|
@ -927,8 +940,8 @@ async function mergePr(prNo, branchName) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function getPrBody(input) {
|
||||
logger.debug(`getPrBody(${(input || '').split('\n')[0]})`);
|
||||
export function getPrBody(input: string) {
|
||||
logger.debug(`getPrBody(${input.split('\n')[0]})`);
|
||||
// Remove any HTML we use
|
||||
return input
|
||||
.replace(/<\/?summary>/g, '**')
|
||||
|
@ -937,12 +950,12 @@ function getPrBody(input) {
|
|||
.substring(0, 30000);
|
||||
}
|
||||
|
||||
function getCommitMessages() {
|
||||
export function getCommitMessages() {
|
||||
logger.debug(`getCommitMessages()`);
|
||||
return config.storage.getCommitMessages();
|
||||
}
|
||||
|
||||
function getVulnerabilityAlerts() {
|
||||
export function getVulnerabilityAlerts() {
|
||||
logger.debug(`getVulnerabilityAlerts()`);
|
||||
return [];
|
||||
}
|
|
@ -1,26 +1,28 @@
|
|||
// SEE for the reference https://github.com/renovatebot/renovate/blob/c3e9e572b225085448d94aa121c7ec81c14d3955/lib/platform/bitbucket/utils.js
|
||||
const url = require('url');
|
||||
const api = require('./bb-got-wrapper');
|
||||
import url from 'url';
|
||||
import api from './bb-got-wrapper';
|
||||
|
||||
// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp250
|
||||
const prStateMapping = {
|
||||
const prStateMapping: any = {
|
||||
MERGED: 'merged',
|
||||
DECLINED: 'closed',
|
||||
OPEN: 'open',
|
||||
};
|
||||
|
||||
const prInfo = pr => ({
|
||||
version: pr.version,
|
||||
number: pr.id,
|
||||
body: pr.description,
|
||||
branchName: pr.fromRef.displayId,
|
||||
title: pr.title,
|
||||
state: prStateMapping[pr.state],
|
||||
createdAt: pr.createdDate,
|
||||
canRebase: false,
|
||||
});
|
||||
export function prInfo(pr: any) {
|
||||
return {
|
||||
version: pr.version,
|
||||
number: pr.id,
|
||||
body: pr.description,
|
||||
branchName: pr.fromRef.displayId,
|
||||
title: pr.title,
|
||||
state: prStateMapping[pr.state],
|
||||
createdAt: pr.createdDate,
|
||||
canRebase: false,
|
||||
};
|
||||
}
|
||||
|
||||
const addMaxLength = (inputUrl, limit = 100) => {
|
||||
const addMaxLength = (inputUrl: string, limit = 100) => {
|
||||
const { search, ...parsedUrl } = url.parse(inputUrl, true); // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
const maxedUrl = url.format({
|
||||
...parsedUrl,
|
||||
|
@ -29,13 +31,19 @@ const addMaxLength = (inputUrl, limit = 100) => {
|
|||
return maxedUrl;
|
||||
};
|
||||
|
||||
const accumulateValues = async (reqUrl, method = 'get', options, limit) => {
|
||||
let accumulator = [];
|
||||
export async function accumulateValues(
|
||||
reqUrl: string,
|
||||
method = 'get',
|
||||
options?: any,
|
||||
limit?: number
|
||||
) {
|
||||
let accumulator: any = [];
|
||||
let nextUrl = addMaxLength(reqUrl, limit);
|
||||
const lowerCaseMethod = method.toLocaleLowerCase();
|
||||
|
||||
while (typeof nextUrl !== 'undefined') {
|
||||
const { body } = await api[lowerCaseMethod](nextUrl, options);
|
||||
// TODO: fix typing
|
||||
const { body } = await (api as any)[lowerCaseMethod](nextUrl, options);
|
||||
accumulator = [...accumulator, ...body.values];
|
||||
if (body.isLastPage !== false) break;
|
||||
|
||||
|
@ -50,13 +58,4 @@ const accumulateValues = async (reqUrl, method = 'get', options, limit) => {
|
|||
}
|
||||
|
||||
return accumulator;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// buildStates,
|
||||
prInfo,
|
||||
accumulateValues,
|
||||
// files: filesEndpoint,
|
||||
// isConflicted,
|
||||
// commitForm,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import got from 'got';
|
||||
|
||||
export interface IGotApiOptions {
|
||||
useCache?: boolean;
|
||||
body?: any;
|
||||
}
|
||||
|
||||
export interface IGotApi {
|
||||
get<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
post<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
put<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
patch<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
head<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
delete<T extends object = any>(
|
||||
url: string,
|
||||
options?: IGotApiOptions
|
||||
): Promise<got.Response<T>>;
|
||||
|
||||
reset(): void;
|
||||
|
||||
setEndpoint(endpoint: string): void;
|
||||
}
|
|
@ -5,6 +5,7 @@ import Git from 'simple-git/promise';
|
|||
import URL from 'url';
|
||||
|
||||
declare module 'fs-extra' {
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function exists(pathLike: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
|
@ -24,7 +25,9 @@ interface ILocalConfig extends IStorageConfig {
|
|||
|
||||
class Storage {
|
||||
private _config: ILocalConfig = {} as any;
|
||||
|
||||
private _git: Git.SimpleGit | undefined;
|
||||
|
||||
private _cwd: string | undefined;
|
||||
|
||||
private async _resetToBranch(branchName: string) {
|
||||
|
@ -50,14 +53,16 @@ class Storage {
|
|||
async initRepo(args: IStorageConfig) {
|
||||
debugger;
|
||||
this.cleanRepo();
|
||||
let config: ILocalConfig = (this._config = { ...args } as any);
|
||||
let cwd = (this._cwd = config.localDir);
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
const config: ILocalConfig = (this._config = { ...args } as any);
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
const cwd = (this._cwd = config.localDir);
|
||||
this._config.branchExists = {};
|
||||
logger.info('Initialising git repository into ' + cwd);
|
||||
const gitHead = join(cwd, '.git/HEAD');
|
||||
let clone = true;
|
||||
|
||||
//TODO: move to private class scope
|
||||
// TODO: move to private class scope
|
||||
async function determineBaseBranch(git: Git.SimpleGit) {
|
||||
// see https://stackoverflow.com/a/44750379/1438522
|
||||
try {
|
||||
|
@ -423,6 +428,7 @@ class Storage {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
cleanRepo() {}
|
||||
|
||||
static getUrl({
|
||||
|
|
|
@ -11,8 +11,13 @@ declare namespace Renovate {
|
|||
|
||||
setMeta(obj: any): void;
|
||||
}
|
||||
|
||||
interface IDict<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-var, vars-on-top
|
||||
declare var logger: Renovate.ILogger;
|
||||
|
||||
declare interface Error {
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
import URL from 'url';
|
||||
|
||||
//TODO: add known properties
|
||||
interface IPlatformConfig {
|
||||
export const defaults: IDict<IPlatformConfig> = {
|
||||
bitbucket: { name: 'Bitbucket', endpoint: 'https://api.bitbucket.org/' },
|
||||
'bitbucket-server': { name: 'Bitbucket Server' },
|
||||
github: { name: 'GitHub', endpoint: 'https://api.github.com/' },
|
||||
gitlab: { name: 'GitLab', endpoint: 'https://gitlab.com/api/v4/' },
|
||||
azure: { name: 'Azure DevOps' },
|
||||
};
|
||||
|
||||
// TODO: add known properties
|
||||
export interface IPlatformConfig {
|
||||
[prop: string]: any;
|
||||
name?: string;
|
||||
endpoint?: string;
|
||||
|
||||
token?: string;
|
||||
}
|
||||
interface IDict<T> {
|
||||
[key: string]: T;
|
||||
|
|
|
@ -154,9 +154,10 @@
|
|||
"@types/bunyan": "1.8.6",
|
||||
"@types/convert-hrtime": "2.0.0",
|
||||
"@types/fs-extra": "7.0.0",
|
||||
"@types/got": "9.4.4",
|
||||
"@types/jest": "24.0.13",
|
||||
"@types/node": "11.13.11",
|
||||
"@types/tmp": "0.1.0",
|
||||
"@types/tmp": "0.0.33",
|
||||
"@typescript-eslint/eslint-plugin": "1.9.0",
|
||||
"@typescript-eslint/parser": "1.9.0",
|
||||
"babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
|
||||
|
|
|
@ -922,14 +922,6 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`platform/bitbucket-server endpoint with no path initRepo() no author 1`] = `
|
||||
Object {
|
||||
"isFork": false,
|
||||
"privateRepo": undefined,
|
||||
"repoFullName": "repo",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`platform/bitbucket-server endpoint with no path initRepo() works 1`] = `
|
||||
Object {
|
||||
"isFork": false,
|
||||
|
@ -2300,14 +2292,6 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`platform/bitbucket-server endpoint with path initRepo() no author 1`] = `
|
||||
Object {
|
||||
"isFork": false,
|
||||
"privateRepo": undefined,
|
||||
"repoFullName": "repo",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`platform/bitbucket-server endpoint with path initRepo() works 1`] = `
|
||||
Object {
|
||||
"isFork": false,
|
|
@ -1,17 +1,23 @@
|
|||
const responses = require('./_fixtures/responses');
|
||||
import responses from './_fixtures/responses';
|
||||
import { IGotApi } from '../../../lib/platform/common';
|
||||
import Storage from '../../../lib/platform/git/storage';
|
||||
|
||||
type BbsApi = typeof import('../../../lib/platform/bitbucket-server');
|
||||
|
||||
describe('platform/bitbucket-server', () => {
|
||||
Object.entries(responses).forEach(([scenarioName, mockResponses]) => {
|
||||
describe(scenarioName, () => {
|
||||
let bitbucket;
|
||||
let api;
|
||||
let hostRules;
|
||||
let GitStorage;
|
||||
let bitbucket: typeof import('../../../lib/platform/bitbucket-server');
|
||||
let api: jest.Mocked<IGotApi>;
|
||||
let hostRules: jest.Mocked<typeof import('../../../lib/util/host-rules')>;
|
||||
let GitStorage: jest.Mock<Storage> & {
|
||||
getUrl: jest.MockInstance<any, any>;
|
||||
};
|
||||
beforeEach(() => {
|
||||
// reset module
|
||||
jest.resetModules();
|
||||
jest.mock('delay');
|
||||
jest.mock('got', () => (url, options) => {
|
||||
jest.mock('got', () => (url: string, options: { method: string }) => {
|
||||
const { method } = options;
|
||||
const body = mockResponses[url] && mockResponses[url][method];
|
||||
if (!body) {
|
||||
|
@ -25,32 +31,36 @@ describe('platform/bitbucket-server', () => {
|
|||
jest.mock('../../../lib/platform/git/storage');
|
||||
jest.mock('../../../lib/util/host-rules');
|
||||
hostRules = require('../../../lib/util/host-rules');
|
||||
api = require('../../../lib/platform/bitbucket-server/bb-got-wrapper');
|
||||
api = require('../../../lib/platform/bitbucket-server/bb-got-wrapper')
|
||||
.api;
|
||||
jest.spyOn(api, 'get');
|
||||
jest.spyOn(api, 'post');
|
||||
jest.spyOn(api, 'put');
|
||||
jest.spyOn(api, 'delete');
|
||||
bitbucket = require('../../../lib/platform/bitbucket-server');
|
||||
GitStorage = require('../../../lib/platform/git/storage');
|
||||
GitStorage.mockImplementation(() => ({
|
||||
initRepo: jest.fn(),
|
||||
cleanRepo: jest.fn(),
|
||||
getFileList: jest.fn(),
|
||||
branchExists: jest.fn(() => true),
|
||||
isBranchStale: jest.fn(() => false),
|
||||
setBaseBranch: jest.fn(),
|
||||
getBranchLastCommitTime: jest.fn(),
|
||||
getAllRenovateBranches: jest.fn(),
|
||||
getCommitMessages: jest.fn(),
|
||||
getFile: jest.fn(),
|
||||
commitFilesToBranch: jest.fn(),
|
||||
mergeBranch: jest.fn(),
|
||||
deleteBranch: jest.fn(),
|
||||
getRepoStatus: jest.fn(),
|
||||
getBranchCommit: jest.fn(
|
||||
() => '0d9c7726c3d628b7e28af234595cfd20febdbf8e'
|
||||
),
|
||||
}));
|
||||
GitStorage.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
initRepo: jest.fn(),
|
||||
cleanRepo: jest.fn(),
|
||||
getFileList: jest.fn(),
|
||||
branchExists: jest.fn(() => true),
|
||||
isBranchStale: jest.fn(() => false),
|
||||
setBaseBranch: jest.fn(),
|
||||
getBranchLastCommitTime: jest.fn(),
|
||||
getAllRenovateBranches: jest.fn(),
|
||||
getCommitMessages: jest.fn(),
|
||||
getFile: jest.fn(),
|
||||
commitFilesToBranch: jest.fn(),
|
||||
mergeBranch: jest.fn(),
|
||||
deleteBranch: jest.fn(),
|
||||
getRepoStatus: jest.fn(),
|
||||
getBranchCommit: jest.fn(
|
||||
() => '0d9c7726c3d628b7e28af234595cfd20febdbf8e'
|
||||
),
|
||||
} as any)
|
||||
);
|
||||
const endpoint =
|
||||
scenarioName === 'endpoint with path'
|
||||
? 'https://stash.renovatebot.com/vcs/'
|
||||
|
@ -75,19 +85,18 @@ describe('platform/bitbucket-server', () => {
|
|||
function initRepo() {
|
||||
return bitbucket.initRepo({
|
||||
repository: 'SOME/repo',
|
||||
gitAuthor: 'bot@renovateapp.com',
|
||||
});
|
||||
} as any);
|
||||
}
|
||||
|
||||
describe('init function', () => {
|
||||
it('should throw if no endpoint', () => {
|
||||
expect(() => {
|
||||
bitbucket.initPlatform({});
|
||||
bitbucket.initPlatform({} as any);
|
||||
}).toThrow();
|
||||
});
|
||||
it('should throw if no username/password', () => {
|
||||
expect(() => {
|
||||
bitbucket.initPlatform({ endpoint: 'endpoint' });
|
||||
bitbucket.initPlatform({ endpoint: 'endpoint' } as any);
|
||||
}).toThrow();
|
||||
});
|
||||
it('should init', () => {
|
||||
|
@ -116,20 +125,12 @@ describe('platform/bitbucket-server', () => {
|
|||
expect(res).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('no author', async () => {
|
||||
expect.assertions(1);
|
||||
const res = await bitbucket.initRepo({
|
||||
repository: 'SOME/repo',
|
||||
});
|
||||
expect(res).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('sends the host as the endpoint option', async () => {
|
||||
expect.assertions(2);
|
||||
GitStorage.getUrl.mockClear();
|
||||
await bitbucket.initRepo({
|
||||
repository: 'SOME/repo',
|
||||
});
|
||||
} as any);
|
||||
expect(GitStorage.getUrl).toHaveBeenCalledTimes(1);
|
||||
expect(GitStorage.getUrl.mock.calls[0][0]).toHaveProperty(
|
||||
'host',
|
||||
|
@ -167,7 +168,7 @@ describe('platform/bitbucket-server', () => {
|
|||
describe('getFileList()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
await initRepo();
|
||||
await bitbucket.branchExists();
|
||||
await bitbucket.branchExists(undefined as any);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -175,7 +176,7 @@ describe('platform/bitbucket-server', () => {
|
|||
describe('isBranchStale()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
await initRepo();
|
||||
await bitbucket.isBranchStale();
|
||||
await bitbucket.isBranchStale(undefined as any);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -197,7 +198,7 @@ describe('platform/bitbucket-server', () => {
|
|||
it('sends to gitFs', async () => {
|
||||
expect.assertions(1);
|
||||
await initRepo();
|
||||
await bitbucket.commitFilesToBranch('some-branch', [{}]);
|
||||
await bitbucket.commitFilesToBranch('some-branch', [{}], 'message');
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -205,21 +206,21 @@ describe('platform/bitbucket-server', () => {
|
|||
describe('getFile()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
await initRepo();
|
||||
await bitbucket.getFile();
|
||||
await bitbucket.getFile('', '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllRenovateBranches()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
await initRepo();
|
||||
await bitbucket.getAllRenovateBranches();
|
||||
await bitbucket.getAllRenovateBranches('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBranchLastCommitTime()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
await initRepo();
|
||||
await bitbucket.getBranchLastCommitTime();
|
||||
await bitbucket.getBranchLastCommitTime('');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -248,9 +249,9 @@ describe('platform/bitbucket-server', () => {
|
|||
expect.assertions(5);
|
||||
await initRepo();
|
||||
|
||||
await expect(bitbucket.addReviewers(null, ['name'])).rejects.toThrow(
|
||||
'not-found'
|
||||
);
|
||||
await expect(
|
||||
bitbucket.addReviewers(null as any, ['name'])
|
||||
).rejects.toThrow('not-found');
|
||||
|
||||
await expect(bitbucket.addReviewers(4, ['name'])).rejects.toThrow(
|
||||
'not-found'
|
||||
|
@ -426,7 +427,7 @@ describe('platform/bitbucket-server', () => {
|
|||
expect.assertions(2);
|
||||
await initRepo();
|
||||
expect(
|
||||
await bitbucket.findPr('userName1/pullRequest1', false)
|
||||
await bitbucket.findPr('userName1/pullRequest1')
|
||||
).toBeUndefined();
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -480,7 +481,7 @@ describe('platform/bitbucket-server', () => {
|
|||
describe('getPr()', () => {
|
||||
it('returns null for no prNo', async () => {
|
||||
expect.assertions(2);
|
||||
expect(await bitbucket.getPr()).toBeNull();
|
||||
expect(await bitbucket.getPr(undefined as any)).toBeNull();
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('gets a PR', async () => {
|
||||
|
@ -497,10 +498,10 @@ describe('platform/bitbucket-server', () => {
|
|||
try {
|
||||
expect(await bitbucket.getPr(3)).toMatchSnapshot();
|
||||
|
||||
global.gitAuthor = { email: 'bot@renovateapp.com' };
|
||||
global.gitAuthor = { email: 'bot@renovateapp.com', name: 'bot' };
|
||||
expect(await bitbucket.getPr(5)).toMatchSnapshot();
|
||||
|
||||
global.gitAuthor = { email: 'jane@example.com' };
|
||||
global.gitAuthor = { email: 'jane@example.com', name: 'jane' };
|
||||
expect(await bitbucket.getPr(5)).toMatchSnapshot();
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
|
@ -520,7 +521,7 @@ describe('platform/bitbucket-server', () => {
|
|||
reviewers: [],
|
||||
fromRef: {},
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
expect(await bitbucket.getPr(5)).toMatchSnapshot();
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -529,7 +530,7 @@ describe('platform/bitbucket-server', () => {
|
|||
describe('getPrFiles()', () => {
|
||||
it('returns empty files', async () => {
|
||||
expect.assertions(1);
|
||||
expect(await bitbucket.getPrFiles(null)).toHaveLength(0);
|
||||
expect(await bitbucket.getPrFiles(null as any)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('returns one file', async () => {
|
||||
|
@ -554,7 +555,7 @@ describe('platform/bitbucket-server', () => {
|
|||
await initRepo();
|
||||
|
||||
await expect(
|
||||
bitbucket.updatePr(null, 'title', 'body')
|
||||
bitbucket.updatePr(null as any, 'title', 'body')
|
||||
).rejects.toThrow('not-found');
|
||||
|
||||
await expect(bitbucket.updatePr(4, 'title', 'body')).rejects.toThrow(
|
||||
|
@ -617,9 +618,9 @@ describe('platform/bitbucket-server', () => {
|
|||
expect.assertions(5);
|
||||
await initRepo();
|
||||
|
||||
await expect(bitbucket.mergePr(null, 'branch')).rejects.toThrow(
|
||||
'not-found'
|
||||
);
|
||||
await expect(
|
||||
bitbucket.mergePr(null as any, 'branch')
|
||||
).rejects.toThrow('not-found');
|
||||
await expect(bitbucket.mergePr(4, 'branch')).rejects.toThrow(
|
||||
'not-found'
|
||||
);
|
||||
|
@ -700,7 +701,7 @@ describe('platform/bitbucket-server', () => {
|
|||
inProgress: 0,
|
||||
failed: 0,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', true)
|
||||
|
@ -722,7 +723,7 @@ describe('platform/bitbucket-server', () => {
|
|||
inProgress: 1,
|
||||
failed: 0,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', true)
|
||||
|
@ -734,7 +735,7 @@ describe('platform/bitbucket-server', () => {
|
|||
inProgress: 0,
|
||||
failed: 0,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', true)
|
||||
|
@ -753,7 +754,7 @@ describe('platform/bitbucket-server', () => {
|
|||
inProgress: 1,
|
||||
failed: 1,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', true)
|
||||
|
@ -772,11 +773,14 @@ describe('platform/bitbucket-server', () => {
|
|||
|
||||
it('throws repository-changed', async () => {
|
||||
expect.assertions(1);
|
||||
GitStorage.mockImplementationOnce(() => ({
|
||||
initRepo: jest.fn(),
|
||||
branchExists: jest.fn(() => Promise.resolve(false)),
|
||||
cleanRepo: jest.fn(),
|
||||
}));
|
||||
GitStorage.mockImplementationOnce(
|
||||
() =>
|
||||
({
|
||||
initRepo: jest.fn(),
|
||||
branchExists: jest.fn(() => Promise.resolve(false)),
|
||||
cleanRepo: jest.fn(),
|
||||
} as any)
|
||||
);
|
||||
await initRepo();
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', true)
|
||||
|
@ -799,7 +803,7 @@ describe('platform/bitbucket-server', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
|
@ -822,7 +826,7 @@ describe('platform/bitbucket-server', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
|
@ -845,7 +849,7 @@ describe('platform/bitbucket-server', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
|
@ -870,7 +874,7 @@ describe('platform/bitbucket-server', () => {
|
|||
isLastPage: true,
|
||||
values: [],
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
|
@ -889,28 +893,28 @@ describe('platform/bitbucket-server', () => {
|
|||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-2',
|
||||
null,
|
||||
null as any,
|
||||
'success'
|
||||
);
|
||||
|
||||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-2',
|
||||
null,
|
||||
null as any,
|
||||
'failed'
|
||||
);
|
||||
|
||||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-2',
|
||||
null,
|
||||
null as any,
|
||||
'failure'
|
||||
);
|
||||
|
||||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-2',
|
||||
null,
|
||||
null as any,
|
||||
'pending'
|
||||
);
|
||||
|
||||
|
@ -921,14 +925,14 @@ describe('platform/bitbucket-server', () => {
|
|||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-2',
|
||||
null,
|
||||
null as any,
|
||||
'success'
|
||||
);
|
||||
|
||||
await bitbucket.setBranchStatus(
|
||||
'somebranch',
|
||||
'context-1',
|
||||
null,
|
||||
null as any,
|
||||
'success'
|
||||
);
|
||||
|
|
@ -31,26 +31,26 @@ describe('platform', () => {
|
|||
});
|
||||
|
||||
it('has same API for github and gitlab', () => {
|
||||
const githubMethods = Object.keys(github);
|
||||
const gitlabMethods = Object.keys(gitlab);
|
||||
const githubMethods = Object.keys(github).sort();
|
||||
const gitlabMethods = Object.keys(gitlab).sort();
|
||||
expect(githubMethods).toMatchObject(gitlabMethods);
|
||||
});
|
||||
|
||||
it('has same API for github and azure', () => {
|
||||
const githubMethods = Object.keys(github);
|
||||
const azureMethods = Object.keys(azure);
|
||||
const githubMethods = Object.keys(github).sort();
|
||||
const azureMethods = Object.keys(azure).sort();
|
||||
expect(githubMethods).toMatchObject(azureMethods);
|
||||
});
|
||||
|
||||
it('has same API for github and Bitbucket', () => {
|
||||
const githubMethods = Object.keys(github);
|
||||
const bitbucketMethods = Object.keys(bitbucket);
|
||||
const githubMethods = Object.keys(github).sort();
|
||||
const bitbucketMethods = Object.keys(bitbucket).sort();
|
||||
expect(bitbucketMethods).toMatchObject(githubMethods);
|
||||
});
|
||||
|
||||
it('has same API for github and Bitbucket Server', () => {
|
||||
const githubMethods = Object.keys(github);
|
||||
const bitbucketMethods = Object.keys(bitbucketServer);
|
||||
const githubMethods = Object.keys(github).sort();
|
||||
const bitbucketMethods = Object.keys(bitbucketServer).sort();
|
||||
expect(bitbucketMethods).toMatchObject(githubMethods);
|
||||
});
|
||||
});
|
||||
|
|
21
yarn.lock
21
yarn.lock
|
@ -521,6 +521,14 @@
|
|||
"@types/minimatch" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/got@9.4.4":
|
||||
version "9.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/got/-/got-9.4.4.tgz#78129553f6a41715df601db43532cd0b87a55d3f"
|
||||
integrity sha512-IGAJokJRE9zNoBdY5csIwN4U5qQn+20HxC0kM+BbUdfTKIXa7bOX/pdhy23NnLBRP8Wvyhx7X5e6EHJs+4d8HA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/tough-cookie" "*"
|
||||
|
||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
|
||||
|
@ -578,10 +586,15 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
|
||||
|
||||
"@types/tmp@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd"
|
||||
integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==
|
||||
"@types/tmp@0.0.33":
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
|
||||
integrity sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=
|
||||
|
||||
"@types/tough-cookie@*":
|
||||
version "2.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d"
|
||||
integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==
|
||||
|
||||
"@types/yargs@^12.0.2", "@types/yargs@^12.0.9":
|
||||
version "12.0.9"
|
||||
|
|
Загрузка…
Ссылка в новой задаче