import commander from "commander" ; import { join } from "path" ; import { Bedrock , Config } from "../../config" ; import { build as buildCmd , exit as exitCmd , populateInheritValueFromConfig , validateForRequiredValues , } from "../../lib/commandBuilder" ; import { createPullRequest } from "../../lib/git/azure" ; import { getCurrentBranch , getOriginUrl , safeGitUrlForLogging , } from "../../lib/gitutils" ; import { hasValue } from "../../lib/validator" ; import { logger } from "../../logger" ; import { BedrockFile } from "../../types" ; import decorator from "./create-revision.decorator.json" ; import { build as buildError , log as logError } from "../../lib/errorBuilder" ; import { errorStatusCode } from "../../lib/errorStatusCode" ; export interface CommandOptions { sourceBranch : string | undefined ; title : string | undefined ; description : string | undefined ; remoteUrl : string | undefined ; personalAccessToken : string | undefined ; orgName : string | undefined ; targetBranch : string | undefined ; } export interface CommandValues { sourceBranch : string ; title : string | undefined ; description : string ; remoteUrl : string ; personalAccessToken : string ; orgName : string ; targetBranch : string | undefined ; } export const getRemoteUrl = async ( remoteUrl ) : Promise < string > => { if ( ! remoteUrl ) { logger . info ( `No remote-url provided, parsing remote from 'origin' on git client` ) ; remoteUrl = await getOriginUrl ( ) ; const safeLoggingUrl = safeGitUrlForLogging ( remoteUrl ) ; logger . info ( `Parsed remote-url for origin: ${ safeLoggingUrl }` ) ; } return remoteUrl ; } ; param targetBranch param bedrockConfig export const getDefaultRings = ( targetBranch , bedrockConfig ) : string [ ] => { const defaultRings = targetBranch ? [ targetBranch ] : Object . entries ( bedrockConfig . rings || { } ) . map ( ( [ branch , config ] ) => ( { branch , ... config } ) ) . filter ( ( ring ) => ! ! ring . isDefault ) . map ( ( ring ) => ring . branch ) ; if ( defaultRings . length === 0 ) { throw buildError ( errorStatusCode . VALIDATION_ERR , { errorKey : "service-create-revision-cmd-err-default-branch-missing" , values : [ join ( __dirname , "bedrock.yaml" ) ] , } ) ; } logger . info ( `Creating pull request against branches: ${ defaultRings . join ( ", " ) }` ) ; return defaultRings ; } ; param sourceBranch export const getSourceBranch = async ( sourceBranch ) : Promise < string > => { if ( ! hasValue ( sourceBranch ) ) { logger . info ( `No source-branch provided, parsing the current branch for git client` ) ; sourceBranch = await getCurrentBranch ( ) ; if ( sourceBranch . length === 0 ) { throw buildError ( errorStatusCode . VALIDATION_ERR , "service-create-revision-cmd-err-source-branch-missing" ) ; } } return sourceBranch ; } ; param defaultRings param values export const makePullRequest = async ( defaultRings , values ) : Promise < void > => { for ( const ring of defaultRings ) { const title = values . title || `[BEDROCK] ${ values . sourceBranch } => ${ ring }` ; await createPullRequest ( title , values . sourceBranch , ring , { description : values . description , orgName : values . orgName , originPushUrl : values . remoteUrl , personalAccessToken : values . personalAccessToken , } ) ; } } ; const populateValues = async ( opts ) : Promise < CommandValues > => { populateInheritValueFromConfig ( decorator , Config ( ) , opts ) ; opts . remoteUrl = await getRemoteUrl ( opts . remoteUrl ) ; opts . sourceBranch = await getSourceBranch ( opts . sourceBranch ) ; validateForRequiredValues ( decorator , opts , true ) ; return { sourceBranch : opts . sourceBranch ! , title : opts . title , description : opts . description || "This is automated PR generated via BEDROCK" , remoteUrl : opts . remoteUrl , personalAccessToken : opts . personalAccessToken ! , orgName : opts . orgName ! , targetBranch : opts . targetBranch , } ; } ; export const execute = async ( opts , exitFn ) : Promise < void > => { try { const values = await populateValues ( opts ) ; const bedrockConfig = Bedrock ( ) ; const defaultRings = getDefaultRings ( values . targetBranch , bedrockConfig ) ; if ( defaultRings . includes ( values . sourceBranch ) ) { throw buildError ( errorStatusCode . VALIDATION_ERR , { errorKey : "service-create-revision-cmd-err-pr-source-branch" , values : [ JSON . stringify ( defaultRings ) , values . sourceBranch ] , } ) ; } await makePullRequest ( defaultRings , values ) ; await exitFn ( 0 ) ; } catch ( err ) { logError ( buildError ( errorStatusCode . CMD_EXE_ERR , "service-create-revision-cmd-failed" , err ) ) ; await exitFn ( 1 ) ; } } ; export const commandDecorator = ( command ) : void => { buildCmd ( command , decorator ) . action ( async ( opts ) => { await execute ( opts , async ( status ) => { await exitCmd ( logger , process . exit , status ) ; } ) ; } ) ; } ;