@ -6,15 +6,38 @@ import { createGithub, IGithub } from "./github-wrapper";
import { getStatusMessageFromRelease } from "./report-processor" ;
import { getStatusMessageFromRelease } from "./report-processor" ;
import { Settings } from "./types" ;
import { Settings } from "./types" ;
interface ICommentOnPullRequestOptions {
interface IRepoOptions {
readonly branch : string ;
readonly branchName : string ;
readonly owner : string ;
readonly reponame : string ;
}
interface IRepoCommitOptions extends IRepoOptions {
readonly rev : string ;
}
interface IPullRequestOptions {
readonly action : string ;
readonly action : string ;
readonly baseRepoOptions : any ;
readonly baseRepoOptions : IRepoOptions ;
readonly headRepoOptions : any ;
readonly headRepoOptions : IRepoCommitOptions ;
readonly pullRequestNumber : number ;
}
}
interface ICheckPullRequestOptions extends ICommentOnPullRequestOptions {
interface IPullRequestOptionsWithGithub extends IPullRequestOptions {
readonly github : IGithub ;
readonly github : IGithub ;
readonly onTenthAttempt : ( ) = > void ;
}
interface ISimpleCallback {
( err? : any ) : void ;
}
interface IHasIssueCallback {
( err? : any , hasIssue? : boolean , issueTitle? : string ) : void ;
}
interface IHasReleasesCallback {
( err? : any , hasReleases? : boolean ) : void ;
}
}
const featureNamePattern = /^feature-(\d+)(?:-[a-zA-Z0-9]+)+$/ ;
const featureNamePattern = /^feature-(\d+)(?:-[a-zA-Z0-9]+)+$/ ;
@ -24,14 +47,14 @@ const masterNamePattern = /^master$/;
const httpNotFound = 404 ;
const httpNotFound = 404 ;
const maxCommentLength = 64000 ;
const maxCommentLength = 64000 ;
const writeComment = ( options , message , callback ) = > options . github . issues . createComment ( {
const writeComment = ( options : IPullRequestOptionsWithGithub , message : string , callback : ISimpleC allback ) = > options . github . issues . createComment ( {
body : message ,
body : message ,
number : options . pullRequestNumber ,
number : options . pullRequestNumber ,
owner : options.baseRepoOptions.owner ,
owner : options.baseRepoOptions.owner ,
repo : options.baseRepoOptions.reponame ,
repo : options.baseRepoOptions.reponame ,
} , callback ) ;
} , callback ) ;
const closePullRequest = ( options , message , callback ) = > writeComment ( options , message , ( err ) = > {
const closePullRequest = ( options : IPullRequestOptionsWithGithub , message : string , callback : ISimpleC allback ) = > writeComment ( options , message , ( err : any ) = > {
if ( err ) {
if ( err ) {
return callback ( err ) ;
return callback ( err ) ;
}
}
@ -44,7 +67,7 @@ const closePullRequest = (options, message, callback) => writeComment(options, m
} , callback ) ;
} , callback ) ;
} ) ;
} ) ;
const checkHasIssue = ( options : ICheck PullRequestOptions , issueNumber , callback ) = > options . github . issues . get ( {
const checkHasIssue = ( options : IPullRequestOptionsWithGithub , issueNumber : number , callback : IHasIssueC allback ) = > options . github . issues . get ( {
number : issueNumber ,
number : issueNumber ,
owner : options.baseRepoOptions.owner ,
owner : options.baseRepoOptions.owner ,
repo : options.baseRepoOptions.reponame ,
repo : options.baseRepoOptions.reponame ,
@ -61,7 +84,7 @@ const checkHasIssue = (options: ICheckPullRequestOptions, issueNumber, callback)
return callback ( "Result is empty" ) ;
return callback ( "Result is empty" ) ;
}
}
if ( result . data . number . toString ( ) !== issueNumber ) {
if ( result . data . number . toString ( ) !== issueNumber . toString ( ) ) {
return callback ( null , false ) ;
return callback ( null , false ) ;
}
}
@ -72,7 +95,7 @@ const checkHasIssue = (options: ICheckPullRequestOptions, issueNumber, callback)
return callback ( null , true , result . data . title ) ;
return callback ( null , true , result . data . title ) ;
} ) ;
} ) ;
const checkHasReleases = ( options : ICheck PullRequestOptions , callback ) = > options . github . repos . getReleases ( {
const checkHasReleases = ( options : IPullRequestOptionsWithGithub , callback : IHasReleasesC allback ) = > options . github . repos . getReleases ( {
owner : options.baseRepoOptions.owner ,
owner : options.baseRepoOptions.owner ,
per_page : 1 ,
per_page : 1 ,
repo : options.baseRepoOptions.reponame ,
repo : options.baseRepoOptions.reponame ,
@ -81,10 +104,10 @@ const checkHasReleases = (options: ICheckPullRequestOptions, callback) => option
return callback ( getReleasesErr ) ;
return callback ( getReleasesErr ) ;
}
}
return callback ( null , result && result . data && result . data . length ) ;
return callback ( null , Boolean ( result && result . data && result . data . length ) ) ;
} ) ;
} ) ;
const checkPullRequest = ( options : ICheck PullRequestOptions , callback ) = > {
const checkPullRequest = ( options : IPullRequestOptionsWithGithub , callback : ISimpleC allback ) = > {
const head = options . headRepoOptions ;
const head = options . headRepoOptions ;
const base = options . baseRepoOptions ;
const base = options . baseRepoOptions ;
@ -93,11 +116,11 @@ const checkPullRequest = (options: ICheckPullRequestOptions, callback) => {
}
}
if ( head . owner === base . owner ) {
if ( head . owner === base . owner ) {
if ( ! versionNamePattern . test ( head . branchn ame ) || ! masterNamePattern . test ( base . branchn ame ) ) {
if ( ! versionNamePattern . test ( head . branchN ame ) || ! masterNamePattern . test ( base . branchN ame ) ) {
return closePullRequest ( options , "Only merging from version to master is allowed" , callback ) ;
return closePullRequest ( options , "Only merging from version to master is allowed" , callback ) ;
}
}
return checkHasReleases ( options , ( hasReleasesErr , hasReleases ) = > {
return checkHasReleases ( options , ( hasReleasesErr , hasReleases? : boolean ) = > {
if ( hasReleasesErr ) {
if ( hasReleasesErr ) {
return writeComment ( options , "Unable to check for releases" , callback ) ;
return writeComment ( options , "Unable to check for releases" , callback ) ;
}
}
@ -107,25 +130,25 @@ const checkPullRequest = (options: ICheckPullRequestOptions, callback) => {
}
}
if ( options . action === "opened" ) {
if ( options . action === "opened" ) {
return writeComment ( options , ` Switching master branch to ${ head . branchn ame } release ` , callback ) ;
return writeComment ( options , ` Switching master branch to ${ head . branchN ame } release ` , callback ) ;
}
}
return process . nextTick ( callback ) ;
return process . nextTick ( callback ) ;
} ) ;
} ) ;
}
}
if ( ! featureNamePattern . test ( head . branchn ame ) ) {
if ( ! featureNamePattern . test ( head . branchN ame ) ) {
return closePullRequest ( options , ` Only merging from feature branch is allowed (pattern: \` ${ featureNamePattern } \` ) ` , callback ) ;
return closePullRequest ( options , ` Only merging from feature branch is allowed (pattern: \` ${ featureNamePattern } \` ) ` , callback ) ;
}
}
if ( ! versionNamePattern . test ( base . branchn ame ) && ! masterNamePattern . test ( base . branchn ame ) ) {
if ( ! versionNamePattern . test ( base . branchN ame ) && ! masterNamePattern . test ( base . branchN ame ) ) {
return closePullRequest ( options , ` Only merging to master or version branch is allowed; merging to ' ${ base . branchn ame } ' is not supported ` , callback ) ;
return closePullRequest ( options , ` Only merging to master or version branch is allowed; merging to ' ${ base . branchN ame } ' is not supported ` , callback ) ;
}
}
const execResult = featureNamePattern . exec ( head . branchn ame ) ;
const execResult = featureNamePattern . exec ( head . branchN ame ) ;
const issueNumber = execResult && execResult [ 1 ] ;
const issueNumber = ( execResult && parseInt ( execResult [ 1 ] , 10 ) ) || 0 ; // execResult will never be empty
return checkHasIssue ( options , issueNumber , ( hasIssueErr , hasIssue , issueTitle ) = > {
return checkHasIssue ( options , issueNumber , ( hasIssueErr , hasIssue? : boolean , issueTitle? : string ) = > {
if ( hasIssueErr ) {
if ( hasIssueErr ) {
return writeComment ( options , ` Unable to check for issue: \ r \ n \ r \ n ${ hasIssueErr } ` , callback ) ;
return writeComment ( options , ` Unable to check for issue: \ r \ n \ r \ n ${ hasIssueErr } ` , callback ) ;
}
}
@ -134,7 +157,7 @@ const checkPullRequest = (options: ICheckPullRequestOptions, callback) => {
return closePullRequest ( options , ` Unable to find issue # ${ issueNumber } ` , callback ) ;
return closePullRequest ( options , ` Unable to find issue # ${ issueNumber } ` , callback ) ;
}
}
const shouldHaveReleases = versionNamePattern . test ( base . branchn ame ) ;
const shouldHaveReleases = versionNamePattern . test ( base . branchN ame ) ;
return checkHasReleases ( options , ( hasReleasesErr , hasReleases ) = > {
return checkHasReleases ( options , ( hasReleasesErr , hasReleases ) = > {
if ( hasReleasesErr ) {
if ( hasReleasesErr ) {
@ -150,7 +173,7 @@ const checkPullRequest = (options: ICheckPullRequestOptions, callback) => {
}
}
if ( options . action === "opened" ) {
if ( options . action === "opened" ) {
return writeComment ( options , ` Merging feature # ${ issueNumber } ( ${ issueTitle } ) to ${ base . branchn ame } ` , callback ) ;
return writeComment ( options , ` Merging feature # ${ issueNumber } ( ${ issueTitle } ) to ${ base . branchN ame } ` , callback ) ;
}
}
return process . nextTick ( callback ) ;
return process . nextTick ( callback ) ;
@ -158,17 +181,17 @@ const checkPullRequest = (options: ICheckPullRequestOptions, callback) => {
} ) ;
} ) ;
} ;
} ;
export const commentOnPullRequest = ( settings : Settings , originalOptions : ICommentOn PullRequestOptions , callback ) = > {
export const commentOnPullRequest = ( settings : Settings , originalOptions : IPullRequestOptions , callback : ISimpleC allback ) = > {
const optionsGithub = {
const options = {
. . . originalOptions ,
. . . originalOptions ,
github : createGithub ( settings , originalOptions . baseRepoOptions . owner ) ,
github : createGithub ( settings , originalOptions . baseRepoOptions . owner ) ,
} ;
} ;
const o ptions = {
const getStatusMessageO ptions = {
. . . optionsGithub ,
. . . options . headRepoOptions ,
onTenthAttempt : ( ) = > writeComment ( optionsGithub , "Waiting for build to finish..." , _ . noop ) ,
onTenthAttempt : ( ) = > writeComment ( options , "Waiting for build to finish..." , _ . noop ) ,
} ;
} ;
return checkPullRequest ( options , ( ) = > getStatusMessageFromRelease ( settings , options . headRepo Options, ( statusMessageErr , statusSuccessMessage ) = > {
return checkPullRequest ( options , ( ) = > getStatusMessageFromRelease ( settings , getStatusMessage Options, ( statusMessageErr , statusSuccessMessage ) = > {
const escapedErr = String ( statusMessageErr || "" ) . substring ( 0 , maxCommentLength )
const escapedErr = String ( statusMessageErr || "" ) . substring ( 0 , maxCommentLength )
. replace ( /`/g , "` " ) ;
. replace ( /`/g , "` " ) ;
const message = statusMessageErr
const message = statusMessageErr