зеркало из https://github.com/electron/trop.git
refactor: start moving tasks to operations dir (#88)
This commit is contained in:
Родитель
456a18a0d8
Коммит
f76980c3f7
|
@ -4,7 +4,7 @@ import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as simpleGit from 'simple-git/promise';
|
import * as simpleGit from 'simple-git/promise';
|
||||||
|
|
||||||
import { initRepo, setUpRemotes } from '../runner';
|
import { initRepo, setupRemotes } from '../../operations/task-runner';
|
||||||
|
|
||||||
let dirObject: { dir?: string } | null = null;
|
let dirObject: { dir?: string } | null = null;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ describe('runner', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set new remotes correctly', async () => {
|
it('should set new remotes correctly', async () => {
|
||||||
await setUpRemotes({
|
await setupRemotes({
|
||||||
dir,
|
dir,
|
||||||
remotes: [{
|
remotes: [{
|
||||||
name: 'origin',
|
name: 'origin',
|
||||||
|
|
|
@ -7,17 +7,15 @@ import * as simpleGit from 'simple-git/promise';
|
||||||
|
|
||||||
import { Label, PullRequest, TropConfig } from './Probot';
|
import { Label, PullRequest, TropConfig } from './Probot';
|
||||||
import queue from './Queue';
|
import queue from './Queue';
|
||||||
import { runCommand } from './runner';
|
import { runCommand } from '../operations/task-runner';
|
||||||
import { CHECK_PREFIX } from '../constants';
|
import { CHECK_PREFIX } from '../constants';
|
||||||
import { PRChange, TropAction, PRStatus } from '../enums';
|
import { PRChange, TropAction, PRStatus } from '../enums';
|
||||||
|
|
||||||
|
import * as labelUtils from '../utils/label-utils';
|
||||||
|
|
||||||
const makeQueue: IQueue = require('queue');
|
const makeQueue: IQueue = require('queue');
|
||||||
const { parse: parseDiff } = require('what-the-diff');
|
const { parse: parseDiff } = require('what-the-diff');
|
||||||
|
|
||||||
export const labelToTargetBranch = (label: Label, prefix: string) => {
|
|
||||||
return label.name.replace(prefix, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
const getGitHub = () => {
|
const getGitHub = () => {
|
||||||
const g = new GitHub();
|
const g = new GitHub();
|
||||||
g.authenticate({
|
g.authenticate({
|
||||||
|
@ -36,8 +34,8 @@ export const labelMergedPR = async (context: Context, pr: PullRequest, targetBra
|
||||||
const labelToAdd = `${labelPrefixes.merged}${targetBranch}`;
|
const labelToAdd = `${labelPrefixes.merged}${targetBranch}`;
|
||||||
const labelToRemove = labelPrefixes.inFlight + targetBranch;
|
const labelToRemove = labelPrefixes.inFlight + targetBranch;
|
||||||
|
|
||||||
await removeLabel(context, prNumber, labelToRemove);
|
await labelUtils.removeLabel(context, prNumber, labelToRemove);
|
||||||
await addLabel(context, prNumber, [labelToAdd]);
|
await labelUtils.addLabel(context, prNumber, [labelToAdd]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,6 +152,7 @@ export const backportImpl = async (robot: Application,
|
||||||
targetRepoRemote =
|
targetRepoRemote =
|
||||||
`https://${process.env.GITHUB_FORK_USER_CLONE_LOGIN}:${process.env.GITHUB_FORK_USER_TOKEN}@github.com/${slug}.git`;
|
`https://${process.env.GITHUB_FORK_USER_CLONE_LOGIN}:${process.env.GITHUB_FORK_USER_TOKEN}@github.com/${slug}.git`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await runCommand({
|
await runCommand({
|
||||||
what: TropAction.SET_UP_REMOTES,
|
what: TropAction.SET_UP_REMOTES,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -269,15 +268,15 @@ export const backportImpl = async (robot: Application,
|
||||||
|
|
||||||
if (labelToRemove) {
|
if (labelToRemove) {
|
||||||
log(`Removing label '${labelToRemove}'`);
|
log(`Removing label '${labelToRemove}'`);
|
||||||
await removeLabel(context, pr.number, labelToRemove);
|
await labelUtils.removeLabel(context, pr.number, labelToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (labelToAdd) {
|
if (labelToAdd) {
|
||||||
log(`Adding label '${labelToAdd}'`);
|
log(`Adding label '${labelToAdd}'`);
|
||||||
await addLabel(context, pr.number, [labelToAdd]);
|
await labelUtils.addLabel(context, pr.number, [labelToAdd]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await addLabel(context, newPr.number!, ['backport', `${targetBranch}`]);
|
await labelUtils.addLabel(context, newPr.number!, ['backport', `${targetBranch}`]);
|
||||||
|
|
||||||
log('Backport complete');
|
log('Backport complete');
|
||||||
}
|
}
|
||||||
|
@ -343,10 +342,10 @@ export const backportImpl = async (robot: Application,
|
||||||
const labelPrefixes = await getLabelPrefixes(context);
|
const labelPrefixes = await getLabelPrefixes(context);
|
||||||
|
|
||||||
const labelToRemove = labelPrefixes.target + targetBranch;
|
const labelToRemove = labelPrefixes.target + targetBranch;
|
||||||
await removeLabel(context, pr.number, labelToRemove);
|
await labelUtils.removeLabel(context, pr.number, labelToRemove);
|
||||||
|
|
||||||
const labelToAdd = labelPrefixes.needsManual + targetBranch;
|
const labelToAdd = labelPrefixes.needsManual + targetBranch;
|
||||||
await addLabel(context, pr.number, [labelToAdd]);
|
await labelUtils.addLabel(context, pr.number, [labelToAdd]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (purpose === BackportPurpose.Check) {
|
if (purpose === BackportPurpose.Check) {
|
||||||
|
@ -378,16 +377,6 @@ export const backportImpl = async (robot: Application,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelExistsOnPR = async (context: Context, labelName: string) => {
|
|
||||||
const labels = await context.github.issues.listLabelsOnIssue(context.repo({
|
|
||||||
number: context.payload.pull_request.number,
|
|
||||||
per_page: 100,
|
|
||||||
page: 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return labels.data.some(label => label.name === labelName);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getLabelPrefixes = async (context: Pick<Context, 'config'>) => {
|
export const getLabelPrefixes = async (context: Pick<Context, 'config'>) => {
|
||||||
const config = await context.config<TropConfig>('config.yml') || {};
|
const config = await context.config<TropConfig>('config.yml') || {};
|
||||||
const target = config.targetLabelPrefix || PRStatus.TARGET;
|
const target = config.targetLabelPrefix || PRStatus.TARGET;
|
||||||
|
@ -411,7 +400,7 @@ export const updateManualBackport = async (
|
||||||
|
|
||||||
if (type === PRChange.OPEN) {
|
if (type === PRChange.OPEN) {
|
||||||
labelToRemove = labelPrefixes.needsManual + pr.base.ref;
|
labelToRemove = labelPrefixes.needsManual + pr.base.ref;
|
||||||
if (!await labelExistsOnPR(context, labelToRemove)) {
|
if (!await labelUtils.labelExistsOnPR(context, labelToRemove)) {
|
||||||
labelToRemove = labelPrefixes.target + pr.base.ref;
|
labelToRemove = labelPrefixes.target + pr.base.ref;
|
||||||
}
|
}
|
||||||
labelToAdd = labelPrefixes.inFlight + pr.base.ref;
|
labelToAdd = labelPrefixes.inFlight + pr.base.ref;
|
||||||
|
@ -441,8 +430,8 @@ please check out #${pr.number}`;
|
||||||
labelToAdd = labelPrefixes.merged + pr.base.ref;
|
labelToAdd = labelPrefixes.merged + pr.base.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
await removeLabel(context, oldPRNumber, labelToRemove);
|
await labelUtils.removeLabel(context, oldPRNumber, labelToRemove);
|
||||||
await addLabel(context, oldPRNumber, [labelToAdd]);
|
await labelUtils.addLabel(context, oldPRNumber, [labelToAdd]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const backportToLabel = async (
|
export const backportToLabel = async (
|
||||||
|
@ -456,7 +445,7 @@ export const backportToLabel = async (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetBranch = labelToTargetBranch(label, labelPrefixes.target);
|
const targetBranch = labelUtils.labelToTargetBranch(label, labelPrefixes.target);
|
||||||
if (!targetBranch) {
|
if (!targetBranch) {
|
||||||
robot.log('Nothing to do');
|
robot.log('Nothing to do');
|
||||||
return;
|
return;
|
||||||
|
@ -482,22 +471,3 @@ export const backportToBranch = async (
|
||||||
robot, context, targetBranch, BackportPurpose.ExecuteBackport, labelToRemove, labelToAdd,
|
robot, context, targetBranch, BackportPurpose.ExecuteBackport, labelToRemove, labelToAdd,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// HELPERS
|
|
||||||
|
|
||||||
const addLabel = async (context: Context, prNumber: number, labelsToAdd: string[]) => {
|
|
||||||
return context.github.issues.addLabels(context.repo({
|
|
||||||
number: prNumber,
|
|
||||||
labels: labelsToAdd,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeLabel = async (context: Context, prNumber: number, labelToRemove: string) => {
|
|
||||||
// If the issue does not have the label, don't try remove it
|
|
||||||
if (!await labelExistsOnPR(context, labelToRemove)) return;
|
|
||||||
|
|
||||||
return context.github.issues.removeLabel(context.repo({
|
|
||||||
number: prNumber,
|
|
||||||
name: labelToRemove,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ import {
|
||||||
backportToBranch,
|
backportToBranch,
|
||||||
backportToLabel,
|
backportToLabel,
|
||||||
getLabelPrefixes,
|
getLabelPrefixes,
|
||||||
labelToTargetBranch,
|
|
||||||
backportImpl,
|
backportImpl,
|
||||||
BackportPurpose,
|
BackportPurpose,
|
||||||
labelMergedPR,
|
labelMergedPR,
|
||||||
updateManualBackport,
|
updateManualBackport,
|
||||||
} from './backport/utils';
|
} from './backport/utils';
|
||||||
|
|
||||||
|
import { labelToTargetBranch } from './utils/label-utils';
|
||||||
import { PullRequest, TropConfig } from './backport/Probot';
|
import { PullRequest, TropConfig } from './backport/Probot';
|
||||||
import { CHECK_PREFIX } from './constants';
|
import { CHECK_PREFIX } from './constants';
|
||||||
import { PRChange } from './enums';
|
import { PRChange } from './enums';
|
||||||
|
|
|
@ -24,6 +24,12 @@ export type RunnerOptions = {
|
||||||
|
|
||||||
const baseDir = path.resolve(os.tmpdir(), 'trop-working');
|
const baseDir = path.resolve(os.tmpdir(), 'trop-working');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the cloned repo trop will use to run backports
|
||||||
|
*
|
||||||
|
* @param {InitRepoOptions} repo and payload for repo initialization
|
||||||
|
* @returns {Object} - an object containing the repo initialization directory
|
||||||
|
*/
|
||||||
export const initRepo = async (options: InitRepoOptions) => {
|
export const initRepo = async (options: InitRepoOptions) => {
|
||||||
const slug = `${options.owner}/${options.repo}`;
|
const slug = `${options.owner}/${options.repo}`;
|
||||||
await fs.mkdirp(path.resolve(baseDir, slug));
|
await fs.mkdirp(path.resolve(baseDir, slug));
|
||||||
|
@ -33,10 +39,15 @@ export const initRepo = async (options: InitRepoOptions) => {
|
||||||
await fs.remove(dir);
|
await fs.remove(dir);
|
||||||
await fs.mkdirp(dir);
|
await fs.mkdirp(dir);
|
||||||
const git = simpleGit(dir);
|
const git = simpleGit(dir);
|
||||||
// This adds support for the target_repo being private as long as the fork user has read access
|
|
||||||
if (process.env.GITHUB_FORK_USER_CLONE_LOGIN) {
|
const forkLogin = process.env.GITHUB_FORK_USER_CLONE_LOGIN;
|
||||||
|
const forkToken = process.env.GITHUB_FORK_USER_TOKEN;
|
||||||
|
|
||||||
|
// Adds support for the target_repo being private as
|
||||||
|
// long as the fork user has read access
|
||||||
|
if (forkLogin) {
|
||||||
await git.clone(
|
await git.clone(
|
||||||
`https://${process.env.GITHUB_FORK_USER_CLONE_LOGIN}:${process.env.GITHUB_FORK_USER_TOKEN}@github.com/${slug}.git`,
|
`https://${forkLogin}:${forkToken}@github.com/${slug}.git`,
|
||||||
'.',
|
'.',
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,7 +73,15 @@ export const initRepo = async (options: InitRepoOptions) => {
|
||||||
return { dir };
|
return { dir };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setUpRemotes = async (options: RemotesOptions) => {
|
/*
|
||||||
|
* Sets up remotes that trop will run backports with.
|
||||||
|
*
|
||||||
|
* @param {RemotesOptions} - an object containing:
|
||||||
|
* 1) dir - the repo directory
|
||||||
|
* 2) remotes - the list of remotes to set on the initialized git repository
|
||||||
|
* @returns {Object} - an object containing the repo initialization directory
|
||||||
|
*/
|
||||||
|
export const setupRemotes = async (options: RemotesOptions) => {
|
||||||
const git = simpleGit(options.dir);
|
const git = simpleGit(options.dir);
|
||||||
|
|
||||||
// Add remotes
|
// Add remotes
|
||||||
|
@ -77,6 +96,17 @@ export const setUpRemotes = async (options: RemotesOptions) => {
|
||||||
return { dir: options.dir };
|
return { dir: options.dir };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs the git commands to apply backports in a series of cherry-picked commits.
|
||||||
|
*
|
||||||
|
* @param {BackportOptions} - an object containing:
|
||||||
|
* 1) dir - the repo directory,
|
||||||
|
* 2) targetBranch - the target branch
|
||||||
|
* 3) patches - a list of patches to apply to the target branch
|
||||||
|
* 3) tempBranch - the temporary branch to PR against the target branch
|
||||||
|
* 4) tempRemote - the temporary remote for use in backporting
|
||||||
|
* @returns {Object} - an object containing the repo initialization directory
|
||||||
|
*/
|
||||||
export const backportCommitsToBranch = async (options: BackportOptions) => {
|
export const backportCommitsToBranch = async (options: BackportOptions) => {
|
||||||
const git = simpleGit(options.dir);
|
const git = simpleGit(options.dir);
|
||||||
// Create branch
|
// Create branch
|
||||||
|
@ -99,12 +129,13 @@ export const backportCommitsToBranch = async (options: BackportOptions) => {
|
||||||
return { dir: options.dir };
|
return { dir: options.dir };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper method for running one of three primary git action sets
|
||||||
export const runCommand = async (options: RunnerOptions): Promise<{ dir: string }> => {
|
export const runCommand = async (options: RunnerOptions): Promise<{ dir: string }> => {
|
||||||
switch (options.what) {
|
switch (options.what) {
|
||||||
case TropAction.INIT_REPO:
|
case TropAction.INIT_REPO:
|
||||||
return await initRepo(options.payload);
|
return await initRepo(options.payload);
|
||||||
case TropAction.SET_UP_REMOTES:
|
case TropAction.SET_UP_REMOTES:
|
||||||
return await setUpRemotes(options.payload);
|
return await setupRemotes(options.payload);
|
||||||
case TropAction.BACKPORT:
|
case TropAction.BACKPORT:
|
||||||
return await backportCommitsToBranch(options.payload);
|
return await backportCommitsToBranch(options.payload);
|
||||||
default:
|
default:
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Context } from 'probot';
|
||||||
|
import { Label } from '../backport/Probot';
|
||||||
|
|
||||||
|
export const addLabel = async (context: Context, prNumber: number, labelsToAdd: string[]) => {
|
||||||
|
return context.github.issues.addLabels(context.repo({
|
||||||
|
number: prNumber,
|
||||||
|
labels: labelsToAdd,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeLabel = async (context: Context, prNumber: number, labelToRemove: string) => {
|
||||||
|
// If the issue does not have the label, don't try remove it
|
||||||
|
if (!await labelExistsOnPR(context, labelToRemove)) return;
|
||||||
|
|
||||||
|
return context.github.issues.removeLabel(context.repo({
|
||||||
|
number: prNumber,
|
||||||
|
name: labelToRemove,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const labelToTargetBranch = (label: Label, prefix: string) => {
|
||||||
|
return label.name.replace(prefix, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const labelExistsOnPR = async (context: Context, labelName: string) => {
|
||||||
|
const labels = await context.github.issues.listLabelsOnIssue(context.repo({
|
||||||
|
number: context.payload.pull_request.number,
|
||||||
|
per_page: 100,
|
||||||
|
page: 1,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return labels.data.some(label => label.name === labelName);
|
||||||
|
};
|
Загрузка…
Ссылка в новой задаче