You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
6.6 KiB
254 lines
6.6 KiB
//
|
|
// build task definitions
|
|
//
|
|
// run any task with "yarn build ${taskName}"
|
|
//
|
|
const path = require('path');
|
|
const livereload = require('gulp-livereload');
|
|
const minimist = require('minimist');
|
|
const { sync: globby } = require('globby');
|
|
const {
|
|
createTask,
|
|
composeSeries,
|
|
composeParallel,
|
|
runTask,
|
|
} = require('./task');
|
|
const createManifestTasks = require('./manifest');
|
|
const createScriptTasks = require('./scripts');
|
|
const createStyleTasks = require('./styles');
|
|
const createStaticAssetTasks = require('./static');
|
|
const createEtcTasks = require('./etc');
|
|
const { BuildType, getBrowserVersionMap } = require('./utils');
|
|
|
|
// Packages required dynamically via browserify configuration in dependencies
|
|
// Required for LavaMoat policy generation
|
|
require('loose-envify');
|
|
require('globalthis');
|
|
require('@babel/plugin-proposal-object-rest-spread');
|
|
require('@babel/plugin-transform-runtime');
|
|
require('@babel/plugin-proposal-class-properties');
|
|
require('@babel/plugin-proposal-optional-chaining');
|
|
require('@babel/plugin-proposal-nullish-coalescing-operator');
|
|
require('@babel/preset-env');
|
|
require('@babel/preset-react');
|
|
require('@babel/core');
|
|
// ESLint-related
|
|
require('@babel/eslint-parser');
|
|
require('@babel/eslint-plugin');
|
|
require('@metamask/eslint-config');
|
|
require('@metamask/eslint-config-nodejs');
|
|
require('eslint');
|
|
require('eslint-config-prettier');
|
|
require('eslint-import-resolver-node');
|
|
require('eslint-plugin-import');
|
|
require('eslint-plugin-jsdoc');
|
|
require('eslint-plugin-node');
|
|
require('eslint-plugin-prettier');
|
|
require('eslint-plugin-react');
|
|
require('eslint-plugin-react-hooks');
|
|
|
|
defineAndRunBuildTasks();
|
|
|
|
function defineAndRunBuildTasks() {
|
|
const {
|
|
buildType,
|
|
entryTask,
|
|
isLavaMoat,
|
|
policyOnly,
|
|
shouldIncludeLockdown,
|
|
shouldLintFenceFiles,
|
|
skipStats,
|
|
} = parseArgv();
|
|
|
|
const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera'];
|
|
|
|
const browserVersionMap = getBrowserVersionMap(browserPlatforms);
|
|
|
|
const ignoredFiles = getIgnoredFiles(buildType);
|
|
|
|
const staticTasks = createStaticAssetTasks({
|
|
livereload,
|
|
browserPlatforms,
|
|
shouldIncludeLockdown,
|
|
buildType,
|
|
});
|
|
|
|
const manifestTasks = createManifestTasks({
|
|
browserPlatforms,
|
|
browserVersionMap,
|
|
buildType,
|
|
});
|
|
|
|
const styleTasks = createStyleTasks({ livereload });
|
|
|
|
const scriptTasks = createScriptTasks({
|
|
browserPlatforms,
|
|
buildType,
|
|
ignoredFiles,
|
|
isLavaMoat,
|
|
livereload,
|
|
policyOnly,
|
|
shouldLintFenceFiles,
|
|
});
|
|
|
|
const { clean, reload, zip } = createEtcTasks({
|
|
livereload,
|
|
browserPlatforms,
|
|
buildType,
|
|
});
|
|
|
|
// build for development (livereload)
|
|
createTask(
|
|
'dev',
|
|
composeSeries(
|
|
clean,
|
|
styleTasks.dev,
|
|
composeParallel(
|
|
scriptTasks.dev,
|
|
staticTasks.dev,
|
|
manifestTasks.dev,
|
|
reload,
|
|
),
|
|
),
|
|
);
|
|
|
|
// build for test development (livereload)
|
|
createTask(
|
|
'testDev',
|
|
composeSeries(
|
|
clean,
|
|
styleTasks.dev,
|
|
composeParallel(
|
|
scriptTasks.testDev,
|
|
staticTasks.dev,
|
|
manifestTasks.testDev,
|
|
reload,
|
|
),
|
|
),
|
|
);
|
|
|
|
// build for prod release
|
|
createTask(
|
|
'prod',
|
|
composeSeries(
|
|
clean,
|
|
styleTasks.prod,
|
|
composeParallel(scriptTasks.prod, staticTasks.prod, manifestTasks.prod),
|
|
zip,
|
|
),
|
|
);
|
|
|
|
// build just production scripts, for LavaMoat policy generation purposes
|
|
createTask('scripts:prod', scriptTasks.prod);
|
|
|
|
// build for CI testing
|
|
createTask(
|
|
'test',
|
|
composeSeries(
|
|
clean,
|
|
styleTasks.prod,
|
|
composeParallel(scriptTasks.test, staticTasks.prod, manifestTasks.test),
|
|
zip,
|
|
),
|
|
);
|
|
|
|
// special build for minimal CI testing
|
|
createTask('styles', styleTasks.prod);
|
|
|
|
// Finally, start the build process by running the entry task.
|
|
runTask(entryTask, { skipStats });
|
|
}
|
|
|
|
function parseArgv() {
|
|
const NamedArgs = {
|
|
BuildType: 'build-type',
|
|
LintFenceFiles: 'lint-fence-files',
|
|
Lockdown: 'lockdown',
|
|
PolicyOnly: 'policy-only',
|
|
SkipStats: 'skip-stats',
|
|
};
|
|
|
|
const argv = minimist(process.argv.slice(2), {
|
|
boolean: [
|
|
NamedArgs.LintFenceFiles,
|
|
NamedArgs.Lockdown,
|
|
NamedArgs.PolicyOnly,
|
|
NamedArgs.SkipStats,
|
|
],
|
|
string: [NamedArgs.BuildType],
|
|
default: {
|
|
[NamedArgs.BuildType]: BuildType.main,
|
|
[NamedArgs.LintFenceFiles]: true,
|
|
[NamedArgs.Lockdown]: true,
|
|
[NamedArgs.PolicyOnly]: false,
|
|
[NamedArgs.SkipStats]: false,
|
|
},
|
|
});
|
|
|
|
if (argv._.length !== 1) {
|
|
throw new Error(
|
|
`Metamask build: Expected a single positional argument, but received "${argv._.length}" arguments.`,
|
|
);
|
|
}
|
|
|
|
const entryTask = argv._[0];
|
|
if (!entryTask) {
|
|
throw new Error('MetaMask build: No entry task specified.');
|
|
}
|
|
|
|
const buildType = argv[NamedArgs.BuildType];
|
|
if (!(buildType in BuildType)) {
|
|
throw new Error(`MetaMask build: Invalid build type: "${buildType}"`);
|
|
}
|
|
|
|
// Manually default this to `false` for dev builds only.
|
|
const shouldLintFenceFiles = process.argv.includes(
|
|
`--${NamedArgs.LintFenceFiles}`,
|
|
)
|
|
? argv[NamedArgs.LintFenceFiles]
|
|
: !/dev/iu.test(entryTask);
|
|
|
|
const policyOnly = argv[NamedArgs.PolicyOnly];
|
|
|
|
return {
|
|
buildType,
|
|
entryTask,
|
|
isLavaMoat: process.argv[0].includes('lavamoat'),
|
|
policyOnly,
|
|
shouldIncludeLockdown: argv[NamedArgs.Lockdown],
|
|
shouldLintFenceFiles,
|
|
skipStats: argv[NamedArgs.SkipStats],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Gets the files to be ignored by the current build, if any.
|
|
*
|
|
* @param {string} currentBuildType - The type of the current build.
|
|
* @returns {string[] | null} The array of files to be ignored by the current
|
|
* build, or `null` if no files are to be ignored.
|
|
*/
|
|
function getIgnoredFiles(currentBuildType) {
|
|
const excludedFiles = Object.values(BuildType)
|
|
// This filter removes "main" and the current build type. The files of any
|
|
// build types that remain in the array will be excluded. "main" is the
|
|
// default build type, and has no files that are excluded from other builds.
|
|
.filter(
|
|
(buildType) =>
|
|
buildType !== BuildType.main && buildType !== currentBuildType,
|
|
)
|
|
// Compute globs targeting files for exclusion for each excluded build
|
|
// type.
|
|
.reduce((excludedGlobs, excludedBuildType) => {
|
|
return excludedGlobs.concat([
|
|
`../../app/**/${excludedBuildType}/**`,
|
|
`../../shared/**/${excludedBuildType}/**`,
|
|
`../../ui/**/${excludedBuildType}/**`,
|
|
]);
|
|
}, [])
|
|
// This creates absolute paths of the form:
|
|
// PATH_TO_REPOSITORY_ROOT/app/**/${excludedBuildType}/**
|
|
.map((pathGlob) => path.resolve(__dirname, pathGlob));
|
|
|
|
return globby(excludedFiles);
|
|
}
|
|
|