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" />
2020-02-05 19:47:25 +01:00
import { Octokit } from "@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
] ) ;
2020-02-05 20:01:02 +01:00
2020-02-21 18:49:02 +01:00
const gh = new Octokit ( {
auth : process.argv [ 2 ]
2020-02-05 20:01:02 +01:00
} ) ;
const inputPR = ( await gh . pulls . get ( { pull_number : + process . env . SOURCE_ISSUE , owner : "microsoft" , repo : "TypeScript" } ) ) . data ;
let remoteName = "origin" ;
if ( inputPR . base . repo . git_url !== ` git:github.com/microsoft/TypeScript ` ) {
runSequence ( [
[ "git" , [ "remote" , "add" , "nonlocal" , inputPR . base . repo . git_url ] ]
] ) ;
remoteName = "nonlocal" ;
}
const baseBranchName = inputPR . base . ref ;
2019-05-31 23:36:39 +02:00
runSequence ( [
2020-02-05 20:01:02 +01:00
[ "git" , [ "fetch" , remoteName , baseBranchName ] ]
2019-05-31 23:36:39 +02:00
] ) ;
2019-05-31 22:42:15 +02:00
let logText = runSequence ( [
2020-02-05 20:01:02 +01:00
[ "git" , [ "log" , ` ${ remoteName } / ${ baseBranchName } .. ${ 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" ) ;
2020-02-05 20:01:02 +01:00
const mergebase = runSequence ( [ [ "git" , [ "merge-base" , ` ${ remoteName } / ${ baseBranchName } ` , 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 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 :
2020-02-21 23:20:19 +01:00
` This cherry-pick was triggered 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 ( {
2020-02-21 18:49:02 +01:00
issue_number : + process . env . SOURCE_ISSUE ,
2019-05-31 22:42:15 +02:00
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 ) {
2020-02-21 18:49:02 +01:00
const gh = new Octokit ( {
auth : process.argv [ 2 ]
2019-05-31 23:12:45 +02:00
} ) ;
await gh . issues . createComment ( {
2020-02-21 18:49:02 +01:00
issue_number : + process . env . SOURCE_ISSUE ,
2019-05-31 23:12:45 +02:00
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
} ) ;