2020-08-11 12:43:27 +01:00
"use strict" ;
var _ _importStar = ( this && this . _ _importStar ) || function ( mod ) {
if ( mod && mod . _ _esModule ) return mod ;
var result = { } ;
if ( mod != null ) for ( var k in mod ) if ( Object . hasOwnProperty . call ( mod , k ) ) result [ k ] = mod [ k ] ;
result [ "default" ] = mod ;
return result ;
} ;
2020-08-27 13:39:07 +01:00
var _ _importDefault = ( this && this . _ _importDefault ) || function ( mod ) {
return ( mod && mod . _ _esModule ) ? mod : { "default" : mod } ;
} ;
2020-08-11 12:43:27 +01:00
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
const commander _1 = require ( "commander" ) ;
2020-08-25 16:19:15 +01:00
const fs = _ _importStar ( require ( "fs" ) ) ;
2020-08-27 13:39:07 +01:00
const md5 _1 = _ _importDefault ( require ( "md5" ) ) ;
2020-08-25 16:19:15 +01:00
const os = _ _importStar ( require ( "os" ) ) ;
2020-08-11 12:43:27 +01:00
const path = _ _importStar ( require ( "path" ) ) ;
2020-08-25 16:19:15 +01:00
const analyze _1 = require ( "./analyze" ) ;
const autobuild _1 = require ( "./autobuild" ) ;
const codeql _1 = require ( "./codeql" ) ;
2020-08-27 14:04:09 +01:00
const config _utils _1 = require ( "./config-utils" ) ;
2020-08-25 16:19:15 +01:00
const init _1 = require ( "./init" ) ;
const languages _1 = require ( "./languages" ) ;
2020-08-11 12:43:27 +01:00
const logging _1 = require ( "./logging" ) ;
const repository _1 = require ( "./repository" ) ;
const upload _lib = _ _importStar ( require ( "./upload-lib" ) ) ;
const program = new commander _1 . Command ( ) ;
program . version ( '0.0.1' ) ;
2020-08-25 16:19:15 +01:00
function parseGithubUrl ( inputUrl ) {
2020-08-11 12:43:27 +01:00
try {
const url = new URL ( inputUrl ) ;
// If we detect this is trying to be to github.com
// then return with a fixed canonical URL.
if ( url . hostname === 'github.com' || url . hostname === 'api.github.com' ) {
2020-08-25 16:19:15 +01:00
return 'https://github.com' ;
2020-08-11 12:43:27 +01:00
}
2020-08-25 16:19:15 +01:00
// Remove the API prefix if it's present
if ( url . pathname . indexOf ( '/api/v3' ) !== - 1 ) {
url . pathname = url . pathname . substring ( 0 , url . pathname . indexOf ( '/api/v3' ) ) ;
2020-08-11 12:43:27 +01:00
}
return url . toString ( ) ;
}
catch ( e ) {
throw new Error ( ` " ${ inputUrl } " is not a valid URL ` ) ;
}
}
2020-08-25 16:19:15 +01:00
function getTempDir ( userInput ) {
2020-08-27 13:39:07 +01:00
const cwd = process . cwd ( ) ;
const cwdHash = md5 _1 . default ( cwd ) ;
const tempDir = path . join ( userInput || process . cwd ( ) , 'codeql-runner' , cwdHash ) ;
2020-08-25 16:19:15 +01:00
if ( ! fs . existsSync ( tempDir ) ) {
fs . mkdirSync ( tempDir , { recursive : true } ) ;
}
return tempDir ;
}
2020-08-27 13:39:07 +01:00
function getToolsDir ( userInput ) {
const toolsDir = userInput || path . join ( os . homedir ( ) , 'codeql-runner-tools' ) ;
2020-08-25 16:19:15 +01:00
if ( ! fs . existsSync ( toolsDir ) ) {
fs . mkdirSync ( toolsDir , { recursive : true } ) ;
}
return toolsDir ;
}
2020-08-27 14:22:16 +01:00
function checkEnvironmentSetup ( config ) {
if ( config . languages . some ( languages _1 . isTracedLanguage ) && ! ( 'ODASA_TRACER_CONFIGURATION' in process . env ) ) {
throw new Error ( "Could not detect 'ODASA_TRACER_CONFIGURATION' in environment. " +
"Make sure that environment variables were correctly exported to future processes. " +
"See end out output from 'init' command for instructions." ) ;
}
}
2020-08-25 16:19:15 +01:00
program
. command ( 'init' )
. description ( 'Initializes CodeQL' )
2020-08-27 10:46:26 +01:00
. requiredOption ( '--repository <repository>' , 'Repository name' )
2020-08-25 16:19:15 +01:00
. requiredOption ( '--github-url <url>' , 'URL of GitHub instance' )
. requiredOption ( '--github-auth <auth>' , 'GitHub Apps token, or of the form "username:token" if using a personal access token' )
. option ( '--languages <languages>' , 'Comma-separated list of languages to analyze. Defaults to trying to detect languages from the repo.' )
. option ( '--queries <queries>' , 'Comma-separated list of additional queries to run. By default, this overrides the same setting in a configuration file.' )
. option ( '--config-file <file>' , 'Path to config file' )
. option ( '--codeql-path <path>' , 'Path to a copy of the CodeQL CLI executable to use. Otherwise downloads a copy.' )
2020-08-27 13:39:07 +01:00
. option ( '--temp-dir <dir>' , 'Directory to use for temporary files. By default will use current working directory.' )
. option ( '--tools-dir <dir>' , 'Directory to use for CodeQL tools and other files to store between runs. By default will use home directory.' )
2020-08-25 16:19:15 +01:00
. option ( '--checkout-path <path>' , 'Checkout path (default: current working directory)' )
2020-08-27 14:26:44 +01:00
. option ( '--debug' , 'Print more verbose output' , false )
2020-08-25 16:19:15 +01:00
. action ( async ( cmd ) => {
2020-08-27 14:26:44 +01:00
const logger = logging _1 . getRunnerLogger ( cmd . debug ) ;
2020-08-25 16:19:15 +01:00
try {
const tempDir = getTempDir ( cmd . tempDir ) ;
2020-08-27 13:39:07 +01:00
const toolsDir = getToolsDir ( cmd . toolsDir ) ;
2020-08-25 16:19:15 +01:00
// Wipe the temp dir
fs . rmdirSync ( tempDir , { recursive : true } ) ;
fs . mkdirSync ( tempDir , { recursive : true } ) ;
let codeql ;
if ( cmd . codeqlPath !== undefined ) {
codeql = codeql _1 . getCodeQL ( cmd . codeqlPath ) ;
}
else {
codeql = await init _1 . initCodeQL ( undefined , cmd . githubAuth , parseGithubUrl ( cmd . githubUrl ) , tempDir , toolsDir , 'runner' , logger ) ;
}
2020-08-27 10:46:26 +01:00
const config = await init _1 . initConfig ( cmd . languages , cmd . queries , cmd . configFile , repository _1 . parseRepositoryNwo ( cmd . repository ) , tempDir , toolsDir , codeql , cmd . checkoutPath || process . cwd ( ) , cmd . githubAuth , parseGithubUrl ( cmd . githubUrl ) , logger ) ;
2020-08-26 13:20:46 +01:00
const tracerConfig = await init _1 . runInit ( codeql , config ) ;
if ( tracerConfig !== undefined ) {
if ( process . platform === 'win32' ) {
const batEnvFile = path . join ( config . tempDir , 'codeql-env.bat' ) ;
const batEnvFileContents = Object . entries ( tracerConfig . env )
. map ( ( [ key , value ] ) => ` Set ${ key } = ${ value } ` )
. join ( '\n' ) ;
fs . writeFileSync ( batEnvFile , batEnvFileContents ) ;
const powershellEnvFile = path . join ( config . tempDir , 'codeql-env.sh' ) ;
const powershellEnvFileContents = Object . entries ( tracerConfig . env )
. map ( ( [ key , value ] ) => ` $ env: ${ key } =" ${ value } " ` )
. join ( '\n' ) ;
fs . writeFileSync ( powershellEnvFile , powershellEnvFileContents ) ;
2020-08-26 16:19:34 +01:00
logger . info ( ` \n CodeQL environment outputted to " ${ batEnvFileContents } " and " ${ powershellEnvFile } ". ` +
2020-08-26 13:20:46 +01:00
` Please export these variables to future processes so the build can tbe traced. ` +
` If using cmd/batch run "call ${ batEnvFileContents } " ` +
` or if using PowerShell run "cat ${ powershellEnvFile } | Invoke-Expression". ` ) ;
}
else {
// Assume that anything that's not windows is using a unix-style shell
const envFile = path . join ( config . tempDir , 'codeql-env.sh' ) ;
const envFileContents = Object . entries ( tracerConfig . env )
2020-08-26 16:40:58 +01:00
// Some vars contain ${LIB} that we do not want to be expanded when executing this script
. map ( ( [ key , value ] ) => ` export ${ key } =" ${ value . replace ( '$' , '\\$' ) } " ` )
2020-08-26 13:20:46 +01:00
. join ( '\n' ) ;
fs . writeFileSync ( envFile , envFileContents ) ;
2020-08-26 16:19:34 +01:00
logger . info ( ` \n CodeQL environment outputted to " ${ envFile } ". ` +
2020-08-26 13:20:46 +01:00
` Please export these variables to future processes so the build can tbe traced, ` +
` for example by running "source ${ envFile } ". ` ) ;
}
}
2020-08-25 16:19:15 +01:00
}
catch ( e ) {
logger . error ( 'Init failed' ) ;
logger . error ( e ) ;
process . exitCode = 1 ;
}
} ) ;
program
. command ( 'autobuild' )
. description ( 'Attempts to automatically build code' )
2020-08-27 14:04:09 +01:00
. option ( '--language <language>' , 'The language to build. By default will try to detect the dominant language.' )
2020-08-27 13:39:07 +01:00
. option ( '--temp-dir <dir>' , 'Directory to use for temporary files. By default will use current working directory.' )
2020-08-27 14:26:44 +01:00
. option ( '--debug' , 'Print more verbose output' , false )
2020-08-25 16:19:15 +01:00
. action ( async ( cmd ) => {
2020-08-27 14:26:44 +01:00
const logger = logging _1 . getRunnerLogger ( cmd . debug ) ;
2020-08-25 16:19:15 +01:00
try {
2020-08-27 14:04:09 +01:00
const config = await config _utils _1 . getConfig ( getTempDir ( cmd . tempDir ) , logger ) ;
2020-08-27 14:22:16 +01:00
checkEnvironmentSetup ( config ) ;
2020-08-27 14:04:09 +01:00
let language = undefined ;
if ( cmd . language !== undefined ) {
language = languages _1 . parseLanguage ( cmd . language ) ;
if ( language === undefined || ! config . languages . includes ( language ) ) {
throw new Error ( ` " ${ cmd . language } " is not a recognised language. ` +
` Known languages in this project are ${ config . languages . join ( ', ' ) } . ` ) ;
}
}
else {
language = autobuild _1 . determineAutobuildLanguage ( config , logger ) ;
}
if ( language !== undefined ) {
await autobuild _1 . runAutobuild ( language , config , logger ) ;
2020-08-25 16:19:15 +01:00
}
}
catch ( e ) {
logger . error ( 'Autobuild failed' ) ;
logger . error ( e ) ;
process . exitCode = 1 ;
}
} ) ;
program
. command ( 'analyze' )
. description ( 'Finishes extracting code and runs CodeQL queries' )
. requiredOption ( '--repository <repository>' , 'Repository name' )
. requiredOption ( '--commit <commit>' , 'SHA of commit that was analyzed' )
. requiredOption ( '--ref <ref>' , 'Name of ref that was analyzed' )
. requiredOption ( '--github-url <url>' , 'URL of GitHub instance' )
. requiredOption ( '--github-auth <auth>' , 'GitHub Apps token, or of the form "username:token" if using a personal access token' )
. option ( '--checkout-path <path>' , 'Checkout path (default: current working directory)' )
. option ( '--no-upload' , 'Do not upload results after analysis' , false )
. option ( '--output-dir <dir>' , 'Directory to output SARIF files to. By default will use temp directory.' )
2020-08-27 13:39:07 +01:00
. option ( '--temp-dir <dir>' , 'Directory to use for temporary files. By default will use current working directory.' )
2020-08-27 14:26:44 +01:00
. option ( '--debug' , 'Print more verbose output' , false )
2020-08-25 16:19:15 +01:00
. action ( async ( cmd ) => {
2020-08-27 14:26:44 +01:00
const logger = logging _1 . getRunnerLogger ( cmd . debug ) ;
2020-08-25 16:19:15 +01:00
try {
const tempDir = getTempDir ( cmd . tempDir ) ;
const outputDir = cmd . outputDir || path . join ( tempDir , 'codeql-sarif' ) ;
2020-08-27 14:04:09 +01:00
const config = await config _utils _1 . getConfig ( getTempDir ( cmd . tempDir ) , logger ) ;
2020-08-27 14:22:16 +01:00
checkEnvironmentSetup ( config ) ;
2020-08-27 14:04:09 +01:00
await analyze _1 . runAnalyze ( repository _1 . parseRepositoryNwo ( cmd . repository ) , cmd . commit , cmd . ref , undefined , undefined , undefined , cmd . checkoutPath || process . cwd ( ) , undefined , cmd . githubAuth , parseGithubUrl ( cmd . githubUrl ) , cmd . upload , 'runner' , outputDir , config , logger ) ;
2020-08-25 16:19:15 +01:00
}
catch ( e ) {
logger . error ( 'Upload failed' ) ;
logger . error ( e ) ;
process . exitCode = 1 ;
}
} ) ;
2020-08-11 12:43:27 +01:00
program
. command ( 'upload' )
. description ( 'Uploads a SARIF file, or all SARIF files from a directory, to code scanning' )
2020-08-12 17:42:47 +01:00
. requiredOption ( '--sarif-file <file>' , 'SARIF file to upload; can also be a directory for uploading multiple' )
2020-08-11 12:43:27 +01:00
. requiredOption ( '--repository <repository>' , 'Repository name' )
. requiredOption ( '--commit <commit>' , 'SHA of commit that was analyzed' )
. requiredOption ( '--ref <ref>' , 'Name of ref that was analyzed' )
. requiredOption ( '--github-url <url>' , 'URL of GitHub instance' )
. requiredOption ( '--github-auth <auth>' , 'GitHub Apps token, or of the form "username:token" if using a personal access token' )
. option ( '--checkout-path <path>' , 'Checkout path (default: current working directory)' )
2020-08-27 14:26:44 +01:00
. option ( '--debug' , 'Print more verbose output' , false )
2020-08-11 12:43:27 +01:00
. action ( async ( cmd ) => {
2020-08-27 14:26:44 +01:00
const logger = logging _1 . getRunnerLogger ( cmd . debug ) ;
2020-08-11 12:43:27 +01:00
try {
2020-08-25 16:19:15 +01:00
await upload _lib . upload ( cmd . sarifFile , repository _1 . parseRepositoryNwo ( cmd . repository ) , cmd . commit , cmd . ref , undefined , undefined , undefined , cmd . checkoutPath || process . cwd ( ) , undefined , cmd . githubAuth , parseGithubUrl ( cmd . githubUrl ) , 'runner' , logger ) ;
2020-08-11 12:43:27 +01:00
}
catch ( e ) {
2020-08-12 18:00:01 +01:00
logger . error ( 'Upload failed' ) ;
2020-08-11 12:43:27 +01:00
logger . error ( e ) ;
2020-08-12 18:00:01 +01:00
process . exitCode = 1 ;
2020-08-11 12:43:27 +01:00
}
} ) ;
program . parse ( process . argv ) ;
2020-08-24 14:21:03 +01:00
//# sourceMappingURL=runner.js.map