@ -5,10 +5,12 @@
//
//
const path = require ( 'path' ) ;
const path = require ( 'path' ) ;
const livereload = require ( 'gulp-livereload' ) ;
const livereload = require ( 'gulp-livereload' ) ;
const minimist = require ( 'minimist' ) ;
const yargs = require ( 'yargs/yargs' ) ;
const { hideBin } = require ( 'yargs/helpers' ) ;
const { sync : globby } = require ( 'globby' ) ;
const { sync : globby } = require ( 'globby' ) ;
const { getVersion } = require ( '../lib/get-version' ) ;
const { getVersion } = require ( '../lib/get-version' ) ;
const { BuildType } = require ( '../lib/build-type' ) ;
const { BuildType } = require ( '../lib/build-type' ) ;
const { TASKS } = require ( './constants' ) ;
const {
const {
createTask ,
createTask ,
composeSeries ,
composeSeries ,
@ -110,7 +112,7 @@ function defineAndRunBuildTasks() {
// build for development (livereload)
// build for development (livereload)
createTask (
createTask (
'dev' ,
TASKS . DEV ,
composeSeries (
composeSeries (
clean ,
clean ,
styleTasks . dev ,
styleTasks . dev ,
@ -125,7 +127,7 @@ function defineAndRunBuildTasks() {
// build for test development (livereload)
// build for test development (livereload)
createTask (
createTask (
'testDev' ,
TASKS . TEST _DEV ,
composeSeries (
composeSeries (
clean ,
clean ,
styleTasks . dev ,
styleTasks . dev ,
@ -140,7 +142,7 @@ function defineAndRunBuildTasks() {
// build for prod release
// build for prod release
createTask (
createTask (
'prod' ,
TASKS . PROD ,
composeSeries (
composeSeries (
clean ,
clean ,
styleTasks . prod ,
styleTasks . prod ,
@ -150,11 +152,11 @@ function defineAndRunBuildTasks() {
) ;
) ;
// build just production scripts, for LavaMoat policy generation purposes
// build just production scripts, for LavaMoat policy generation purposes
createTask ( 'scripts:prod' , scriptTasks . prod ) ;
createTask ( TASKS . SCRIPTS _PROD , scriptTasks . prod ) ;
// build for CI testing
// build for CI testing
createTask (
createTask (
'test' ,
TASKS . TEST ,
composeSeries (
composeSeries (
clean ,
clean ,
styleTasks . prod ,
styleTasks . prod ,
@ -164,89 +166,108 @@ function defineAndRunBuildTasks() {
) ;
) ;
// special build for minimal CI testing
// special build for minimal CI testing
createTask ( 'styles' , styleTasks . prod ) ;
createTask ( TASKS . styles , styleTasks . prod ) ;
// Finally, start the build process by running the entry task.
// Finally, start the build process by running the entry task.
runTask ( entryTask , { skipStats } ) ;
runTask ( entryTask , { skipStats } ) ;
}
}
function parseArgv ( ) {
function parseArgv ( ) {
const NamedArgs = {
const { argv } = yargs ( hideBin ( process . argv ) )
ApplyLavaMoat : 'apply-lavamoat' ,
. usage ( '$0 <task> [options]' , 'Build the MetaMask extension.' , ( _yargs ) =>
BuildType : 'build-type' ,
_yargs
BuildVersion : 'build-version' ,
. positional ( 'task' , {
LintFenceFiles : 'lint-fence-files' ,
description : ` The task to run. There are a number of main tasks, each of which calls other tasks internally. The main tasks are:
Lockdown : 'lockdown' ,
PolicyOnly : 'policy-only' ,
SkipStats : 'skip-stats' ,
} ;
const argv = minimist ( process . argv . slice ( 2 ) , {
boolean : [
NamedArgs . ApplyLavaMoat ,
NamedArgs . LintFenceFiles ,
NamedArgs . Lockdown ,
NamedArgs . PolicyOnly ,
NamedArgs . SkipStats ,
] ,
string : [ NamedArgs . BuildType , NamedArgs . BuildVersion ] ,
default : {
[ NamedArgs . ApplyLavaMoat ] : true ,
[ NamedArgs . BuildType ] : BuildType . main ,
[ NamedArgs . BuildVersion ] : '0' ,
[ NamedArgs . LintFenceFiles ] : true ,
[ NamedArgs . Lockdown ] : true ,
[ NamedArgs . PolicyOnly ] : false ,
[ NamedArgs . SkipStats ] : false ,
} ,
} ) ;
if ( argv . _ . length !== 1 ) {
prod : Create an optimized build for a production environment .
throw new Error (
` Metamask build: Expected a single positional argument, but received " ${ argv . _ . length } " arguments. ` ,
) ;
}
const entryTask = argv . _ [ 0 ] ;
dev : Create an unoptimized , live - reloading build for local development .
if ( ! entryTask ) {
throw new Error ( 'MetaMask build: No entry task specified.' ) ;
}
const buildType = argv [ NamedArgs . BuildType ] ;
test : Create an optimized build for running e2e tests .
if ( ! ( buildType in BuildType ) ) {
throw new Error ( ` MetaMask build: Invalid build type: " ${ buildType } " ` ) ;
}
const rawBuildVersion = argv [ NamedArgs . BuildVersion ] ;
testDev : Create an unoptimized , live - reloading build for debugging e2e tests . ` ,
const buildVersion = Number . parseInt ( rawBuildVersion , 10 ) ;
type : 'string' ,
if ( rawBuildVersion . match ( /^\d+$/u ) === null || Number . isNaN ( buildVersion ) ) {
} )
. option ( 'apply-lavamoat' , {
default : true ,
description :
'Whether to use LavaMoat. Setting this to `false` can be useful during development if you want to handle LavaMoat errors later.' ,
type : 'boolean' ,
} )
. option ( 'build-type' , {
default : BuildType . main ,
description : 'The type of build to create.' ,
choices : Object . keys ( BuildType ) ,
} )
. option ( 'build-version' , {
default : 0 ,
description :
'The build version. This is set only for non-main build types. The build version is used in the "prerelease" segment of the extension version, e.g. `[major].[minor].[patch]-[build-type].[build-version]`' ,
type : 'number' ,
} )
. option ( 'lint-fence-files' , {
description :
'Whether files with code fences should be linted after fences have been removed. The build will fail if linting fails. This defaults to `false` if the entry task is `dev` or `testDev`. Otherwise this defaults to `true`.' ,
type : 'boolean' ,
} )
. option ( 'lockdown' , {
default : true ,
description :
'Whether to include SES lockdown files in the extension bundle. Setting this to `false` can be useful during development if you want to handle lockdown errors later.' ,
type : 'boolean' ,
} )
. option ( 'policy-only' , {
default : false ,
description :
'Stop the build after generating the LavaMoat policy, skipping any writes to disk other than the LavaMoat policy itself.' ,
type : 'boolean' ,
} )
. option ( 'skip-stats' , {
default : false ,
description :
'Whether to skip logging the time to completion for each task to the console. This is meant primarily for internal use, to prevent duplicate logging.' ,
hidden : true ,
type : 'boolean' ,
} )
. check ( ( args ) => {
if ( ! Number . isInteger ( args . buildVersion ) ) {
throw new Error (
throw new Error (
` MetaMask build: Invalid build version: " ${ rawBuildVersion } " ` ,
` Expected integer for 'build-version', got ' ${ args . buildVersion } ' ` ,
) ;
) ;
} else if ( ! Object . values ( TASKS ) . includes ( args . task ) ) {
throw new Error ( ` Invalid task: ' ${ args . task } ' ` ) ;
}
}
return true ;
// Manually default this to `false` for dev builds only.
} ) ,
const shouldLintFenceFiles = process . argv . includes (
` -- ${ NamedArgs . LintFenceFiles } ` ,
)
)
? argv [ NamedArgs . LintFenceFiles ]
// TODO: Enable `.strict()` after this issue is resolved: https://github.com/LavaMoat/LavaMoat/issues/344
: ! /dev/iu . test ( entryTask ) ;
. help ( 'help' ) ;
const policyOnly = argv [ NamedArgs . PolicyOnly ] ;
const {
applyLavamoat : applyLavaMoat ,
buildType ,
buildVersion ,
lintFenceFiles ,
lockdown ,
policyOnly ,
skipStats ,
task ,
} = argv ;
// Manually default this to `false` for dev builds only.
const shouldLintFenceFiles = lintFenceFiles ? ? ! /dev/iu . test ( task ) ;
const version = getVersion ( buildType , buildVersion ) ;
const version = getVersion ( buildType , buildVersion ) ;
return {
return {
// Should we apply LavaMoat to the build output?
applyLavaMoat ,
applyLavaMoat : argv [ NamedArgs . ApplyLavaMoat ] ,
buildType ,
buildType ,
entryTask ,
entryTask : task ,
// Is this process running in lavamoat-node?
isLavaMoat : process . argv [ 0 ] . includes ( 'lavamoat' ) ,
isLavaMoat : process . argv [ 0 ] . includes ( 'lavamoat' ) ,
policyOnly ,
policyOnly ,
shouldIncludeLockdown : argv [ NamedArgs . Lockdown ] ,
shouldIncludeLockdown : l ockdown,
shouldLintFenceFiles ,
shouldLintFenceFiles ,
skipStats : argv [ NamedArgs . SkipStats ] ,
skipStats ,
version ,
version ,
} ;
} ;
}
}