1+ /**
2+ * @license
3+ * Copyright Google Inc. All Rights Reserved.
4+ *
5+ * Use of this source code is governed by an MIT-style license that can be
6+ * found in the LICENSE file at https://angular.io/license
7+ */
8+
9+ // tslint:disable:no-console
10+ // ** IMPORTANT **
11+ // This script cannot use external dependencies because it needs to run before they are installed.
12+
13+ const util = require ( 'util' ) ;
14+ const https = require ( 'https' ) ;
15+ const child_process = require ( 'child_process' ) ;
16+ const exec = util . promisify ( child_process . exec ) ;
17+
18+ function determineTargetBranch ( repository , prNumber ) {
19+ const pullsUrl = `https://api.github.com/repos/${ repository } /pulls/${ prNumber } ` ;
20+ // GitHub requires a user agent: https://developer.github.com/v3/#user-agent-required
21+ const options = { headers : { 'User-Agent' : repository } } ;
22+
23+ return new Promise ( ( resolve , reject ) => {
24+ https . get ( pullsUrl , options , ( res ) => {
25+ const { statusCode } = res ;
26+ const contentType = res . headers [ 'content-type' ] ;
27+
28+ let error ;
29+ if ( statusCode !== 200 ) {
30+ error = new Error ( `Request Failed.\nStatus Code: ${ statusCode } .\nResponse: ${ res } .\n' +` ) ;
31+ } else if ( ! / ^ a p p l i c a t i o n \/ j s o n / . test ( contentType ) ) {
32+ error = new Error ( 'Invalid content-type.\n' +
33+ `Expected application/json but received ${ contentType } ` ) ;
34+ }
35+ if ( error ) {
36+ reject ( error ) ;
37+ res . resume ( ) ;
38+ return ;
39+ }
40+
41+ res . setEncoding ( 'utf8' ) ;
42+ let rawData = '' ;
43+ res . on ( 'data' , ( chunk ) => { rawData += chunk ; } ) ;
44+ res . on ( 'end' , ( ) => {
45+ try {
46+ const parsedData = JSON . parse ( rawData ) ;
47+ resolve ( parsedData [ 'base' ] [ 'ref' ] ) ;
48+ } catch ( e ) {
49+ reject ( e ) ;
50+ }
51+ } ) ;
52+ } ) . on ( 'error' , ( e ) => {
53+ reject ( e ) ;
54+ } ) ;
55+ } ) ;
56+ }
57+
58+ if ( process . argv . length != 4 ) {
59+ console . error ( `This script requires the GitHub repository and PR number as arguments.` ) ;
60+ console . error ( `Example: node scripts/rebase-pr.js angular/angular 123` ) ;
61+ process . exitCode = 1 ;
62+ return ;
63+ }
64+
65+ const repository = process . argv [ 2 ] ;
66+ const prNumber = process . argv [ 3 ] ;
67+ let targetBranch ;
68+
69+
70+ return Promise . resolve ( )
71+ . then ( ( ) => {
72+ console . log ( `Determining target branch for PR ${ prNumber } on ${ repository } .` ) ;
73+ return determineTargetBranch ( repository , prNumber ) ;
74+ } )
75+ . then ( target => {
76+ targetBranch = target ;
77+ console . log ( `Target branch is ${ targetBranch } .` ) ;
78+ } )
79+ . then ( ( ) => {
80+ console . log ( `Fetching ${ targetBranch } from origin.` ) ;
81+ return exec ( `git fetch origin ${ targetBranch } ` ) ;
82+ } )
83+ . then ( target => {
84+ console . log ( `Rebasing current branch on ${ targetBranch } .` ) ;
85+ return exec ( `git rebase origin/${ targetBranch } ` ) ;
86+ } )
87+ . then ( ( ) => console . log ( 'Rebase successfull.' ) )
88+ . catch ( err => {
89+ console . log ( 'Failed to rebase on top or target branch.\n' ) ;
90+ console . error ( err ) ;
91+ process . exitCode = 1 ;
92+ } ) ;
0 commit comments