2019-05-31 22:42:15 +02:00
/// <reference lib="esnext.asynciterable" />
// Must reference esnext.asynciterable lib, since octokit uses AsyncIterable internally
/// <reference types="node" />
import Octokit = require ( "@octokit/rest" ) ;
2019-05-31 23:12:45 +02:00
const { runSequence } = require ( "./run-sequence" ) ;
2019-05-31 22:42:15 +02:00
import fs = require ( "fs" ) ;
import path = require ( "path" ) ;
const userName = process . env . GH_USERNAME ;
const reviewers = process . env . REQUESTING_USER ? [ process . env . REQUESTING_USER ] : [ "weswigham" , "RyanCavanaugh" ] ;
const branchName = ` pick/ ${ process . env . SOURCE_ISSUE } / ${ process . env . TARGET_BRANCH } ` ;
const remoteUrl = ` https:// ${ process . argv [ 2 ] } @github.com/ ${ userName } /TypeScript.git ` ;
2019-08-16 23:17:03 +02:00
const produceLKG = ! ! process . env . PRODUCE_LKG ;
2019-05-31 22:42:15 +02:00
async function main() {
2019-05-31 23:12:45 +02:00
if ( ! process . env . TARGET_BRANCH ) {
throw new Error ( "Target branch not specified" ) ;
}
if ( ! process . env . SOURCE_ISSUE ) {
throw new Error ( "Source issue not specified" ) ;
}
2019-05-31 22:42:15 +02:00
const currentSha = runSequence ( [
[ "git" , [ "rev-parse" , "HEAD" ] ]
] ) ;
const currentAuthor = runSequence ( [
[ "git" , [ "log" , "-1" , ` --pretty="%aN <%aE>" ` ] ]
2019-05-31 23:36:39 +02:00
] ) ;
runSequence ( [
[ "git" , [ "fetch" , "origin" , "master" ] ]
] ) ;
2019-05-31 22:42:15 +02:00
let logText = runSequence ( [
2019-05-31 23:46:33 +02:00
[ "git" , [ "log" , ` origin/master.. ${ currentSha . trim ( ) } ` , ` --pretty="%h %s%n%b" ` , "--reverse" ] ]
2019-05-31 22:42:15 +02:00
] ) ;
logText = ` Cherry-pick PR # ${ process . env . SOURCE_ISSUE } into ${ process . env . TARGET_BRANCH }
Component commits :
2019-06-14 08:46:02 +02:00
$ { logText . trim ( ) } ` ;
2019-05-31 22:42:15 +02:00
const logpath = path . join ( __dirname , "../" , "logmessage.txt" ) ;
2019-06-21 23:34:26 +02:00
const mergebase = runSequence ( [ [ "git" , [ "merge-base" , "origin/master" , currentSha ] ] ] ) . trim ( ) ;
2019-05-31 22:42:15 +02:00
runSequence ( [
[ "git" , [ "checkout" , "-b" , "temp-branch" ] ] ,
2019-06-21 23:34:26 +02:00
[ "git" , [ "reset" , mergebase , "--soft" ] ]
2019-05-31 22:42:15 +02:00
] ) ;
fs . writeFileSync ( logpath , logText ) ;
runSequence ( [
2019-05-31 23:36:39 +02:00
[ "git" , [ "commit" , "-F" , logpath , ` --author=" ${ currentAuthor . trim ( ) } " ` ] ]
2019-05-31 22:42:15 +02:00
] ) ;
fs . unlinkSync ( logpath ) ;
const squashSha = runSequence ( [
[ "git" , [ "rev-parse" , "HEAD" ] ]
] ) ;
runSequence ( [
[ "git" , [ "checkout" , process . env . TARGET_BRANCH ] ] , // checkout the target branch
[ "git" , [ "checkout" , "-b" , branchName ] ] , // create a new branch
2019-08-16 22:01:18 +02:00
[ "git" , [ "cherry-pick" , squashSha . trim ( ) ] ] ,
] ) ;
if ( produceLKG ) {
runSequence ( [
[ "gulp" , [ "LKG" ] ] ,
[ "git" , [ "add" , "lib" ] ] ,
[ "git" , [ "commit" , "-m" , ` "Update LKG" ` ] ]
] ) ;
}
runSequence ( [
2019-05-31 22:42:15 +02:00
[ "git" , [ "remote" , "add" , "fork" , remoteUrl ] ] , // Add the remote fork
[ "git" , [ "push" , "--set-upstream" , "fork" , branchName , "-f" ] ] // push the branch
] ) ;
const gh = new Octokit ( ) ;
gh . authenticate ( {
type : "token" ,
token : process.argv [ 2 ]
} ) ;
const r = await gh . pulls . create ( {
owner : "Microsoft" ,
repo : "TypeScript" ,
maintainer_can_modify : true ,
title : ` 🤖 Cherry-pick PR # ${ process . env . SOURCE_ISSUE } into ${ process . env . TARGET_BRANCH } ` ,
head : ` ${ userName } : ${ branchName } ` ,
base : process.env.TARGET_BRANCH ,
body :
` This cherry-pick was triggerd by a request on https://github.com/Microsoft/TypeScript/pull/ ${ process . env . SOURCE_ISSUE }
2019-08-16 22:01:18 +02:00
Please review the diff and merge if no changes are unexpected . $ { produceLKG ? ` An LKG update commit is included seperately from the base change. ` : "" }
2019-05-31 23:54:36 +02:00
You can view the cherry - pick log [ here ] ( https : //typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary).
2019-05-31 22:42:15 +02:00
2019-05-31 23:54:36 +02:00
cc $ { reviewers . map ( r = > "@" + r ) . join ( " " ) } ` ,
2019-05-31 22:42:15 +02:00
} ) ;
const num = r . data . number ;
console . log ( ` Pull request ${ num } created. ` ) ;
await gh . issues . createComment ( {
number : + process . env . SOURCE_ISSUE ,
owner : "Microsoft" ,
repo : "TypeScript" ,
body : ` Hey @ ${ process . env . REQUESTING_USER } , I've opened # ${ num } for you. `
} ) ;
}
main ( ) . catch ( async e = > {
console . error ( e ) ;
process . exitCode = 1 ;
2019-05-31 23:12:45 +02:00
if ( process . env . SOURCE_ISSUE ) {
const gh = new Octokit ( ) ;
gh . authenticate ( {
type : "token" ,
token : process.argv [ 2 ]
} ) ;
await gh . issues . createComment ( {
number : + process . env . SOURCE_ISSUE ,
owner : "Microsoft" ,
repo : "TypeScript" ,
body : ` Hey @ ${ process . env . REQUESTING_USER } , I couldn't open a PR with the cherry-pick. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId= ${ process . env . BUILD_BUILDID } &_a=summary)). You may need to squash and pick this PR into ${ process . env . TARGET_BRANCH } manually. `
} ) ;
}
2019-06-14 08:46:02 +02:00
} ) ;