Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏗 Replace gulp with the amp task runner #33315

Merged
merged 11 commits into from
Mar 18, 2021
Prev Previous commit
Next Next commit
Replace gulp with the amp task runner
  • Loading branch information
rsimha committed Mar 18, 2021
commit 08649a0151198ad674842202785221ac3d794810
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ module.exports = {
'sort-requires/sort-requires': 2,
},
'overrides': [
{
'files': ['amp.js', 'gulp-deprecated.js'],
'globals': {
'require': false,
},
},
{
'files': [
'test/**/*.js',
Expand Down
103 changes: 16 additions & 87 deletions gulpfile.js → amp.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env node
/**
* Copyright 2019 The AMP HTML Authors. All Rights Reserved.
* Copyright 2021 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,100 +15,33 @@
* limitations under the License.
*/

/* global require, process */

const argv = require('minimist')(process.argv.slice(2));
const gulp = require('gulp');
const {cyan, red} = require('kleur/colors');
const {isCiBuild} = require('./build-system/common/ci');
const {log} = require('./build-system/common/logging');

/**
* Helper that creates the tasks in AMP's toolchain based on what's being done:
* - If `gulp --tasks` has been invoked, eagerly load all task functions so we
* can print detailed information about their names, flags, usage, etc.
* - If a single gulp task has been invoked, create a wrapper that lazily loads
* individual task functions from their source files. After that, check the
* flag usage for the current task and load only those source file(s) used by
* the task that was invoked.
* @param {string} taskName
* @param {string} taskFuncName
* @param {string} taskSourceFileName
*/
function createTask(taskName, taskFuncName, taskSourceFileName) {
const isGulpTasks = argv._.length == 0 && argv.tasks == true; // gulp --tasks
const taskSourceFilePath = `./build-system/tasks/${taskSourceFileName}`;
if (isGulpTasks) {
const taskFunc = require(taskSourceFilePath)[taskFuncName];
gulp.task(taskName, taskFunc);
} else {
gulp.task(taskName, (callback) => {
const taskFunc = require(taskSourceFilePath)[taskFuncName];
checkFlags(taskName, taskFunc, callback);
return taskFunc(callback);
});
}
}
const {
createTask,
finalizeRunner,
} = require('./build-system/tasks/amp-task-runner');

/**
* Checks if the flags passed in to a task are valid.
* @param {string} name
* @param {function} taskFunc
* @param {function} callback
*/
function checkFlags(name, taskFunc, callback) {
const validFlags = taskFunc.flags ? Object.keys(taskFunc.flags) : [];
if (isCiBuild()) {
validFlags.push('color'); // Used to enable log coloring during CI.
}
const usedFlags = Object.keys(argv).slice(1); // Skip the '_' argument
const invalidFlags = [];
usedFlags.forEach((flag) => {
if (!validFlags.includes(flag)) {
invalidFlags.push(`--${flag}`);
}
});
if (invalidFlags.length > 0) {
log(
red('ERROR:'),
'Found invalid flags for',
cyan(`gulp ${name}`) + ':',
cyan(invalidFlags.join(', '))
);
log('For detailed usage information, run', cyan('gulp --tasks') + '.');
if (validFlags.length > 0) {
log('Valid flags for', cyan(`gulp ${name}`) + ':');
validFlags.forEach((key) => {
log(cyan(`\t--${key}`) + `: ${taskFunc.flags[key]}`);
});
}
const reason = new Error('Found invalid flags');
reason.showStack = false;
callback(reason);
}
}

/**
* All the gulp tasks. Keep this list alphabetized.
* All the AMP tasks. Keep this list alphabetized.
*
* The three params used below are:
* 1. Name of the gulp task to be invoked E.g. gulp default
* 1. Name of the amp task to be invoked E.g. amp default
* 2. Name of the function in the source file. E.g. defaultTask()
* 3. Basename of the source file in build-system/tasks/. E.g. build-system/tasks/default-task.js
*/

createTask('analytics-vendor-configs','analyticsVendorConfigs','analytics-vendor-configs'); // prettier-ignore
createTask('analytics-vendor-configs', 'analyticsVendorConfigs', 'analytics-vendor-configs'); // prettier-ignore
createTask('ava', 'ava', 'ava');
createTask('babel-plugin-tests', 'babelPluginTests', 'babel-plugin-tests');
createTask('build', 'build', 'build');
createTask('bundle-size', 'bundleSize', 'bundle-size');
createTask('caches-json', 'cachesJson', 'caches-json');
createTask('check-analytics-vendors-list', 'checkAnalyticsVendorsList', 'check-analytics-vendors-list'); // prettier-ignore
createTask('check-exact-versions', 'checkExactVersions','check-exact-versions'); // prettier-ignore
createTask('check-links', 'checkLinks', 'check-links');
createTask('check-owners', 'checkOwners', 'check-owners');
createTask('check-renovate-config','checkRenovateConfig','check-renovate-config'); // prettier-ignore
createTask('check-sourcemaps', 'checkSourcemaps', 'check-sourcemaps');
createTask('check-types', 'checkTypes', 'check-types');
createTask('check-video-interface-list', 'checkVideoInterfaceList', 'check-video-interface-list'); // prettier-ignore
createTask('cherry-pick', 'cherryPick', 'cherry-pick');
createTask('clean', 'clean', 'clean');
createTask('codecov-upload', 'codecovUpload', 'codecov-upload');
Expand Down Expand Up @@ -141,14 +75,9 @@ createTask('unit', 'unit', 'unit');
createTask('update-packages', 'updatePackages', 'update-packages');
createTask('validator', 'validator', 'validator');
createTask('validator-webui', 'validatorWebui', 'validator');
createTask(
'check-video-interface-list',
'checkVideoInterfaceList',
'check-video-interface-list'
);
createTask(
'check-analytics-vendors-list',
'checkAnalyticsVendorsList',
'check-analytics-vendors-list'
);
createTask('visual-diff', 'visualDiff', 'visual-diff');

/**
* Finalize the task runner after all tasks have been created.
*/
finalizeRunner();
127 changes: 0 additions & 127 deletions build-system/common/check-package-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,12 @@
* so it must work with vanilla NodeJS code.
* github.com/ampproject/amphtml/pull/19386
*/
const fs = require('fs');
const https = require('https');
const {getStdout} = require('./process');

const setupInstructionsUrl =
'https://github.com/ampproject/amphtml/blob/master/contributing/getting-started-quick.md#one-time-setup';
const nodeDistributionsUrl = 'https://nodejs.org/dist/index.json';
const gulpHelpUrl =
'https://medium.com/gulpjs/gulp-sips-command-line-interface-e53411d4467';

const wrongGulpPaths = [
'/bin/',
'/sbin/',
'/usr/bin/',
'/usr/sbin/',
'/usr/local/bin/',
'/usr/local/sbin/',
];

const warningDelaySecs = 10;

Expand Down Expand Up @@ -223,120 +211,6 @@ function logNpmVersion() {
);
}

/**
* Gets the PATH variable from the parent shell of the node process
*
* @return {string}
*/
function getParentShellPath() {
const nodePath = process.env.PATH;
const pathSeparator = process.platform == 'win32' ? ';' : ':';
// nodejs adds a few extra variables to $PATH, ending with '../../bin/node-gyp-bin'.
// See https://github.com/nodejs/node-convergence-archive/blob/master/deps/npm/lib/utils/lifecycle.js#L81-L85
return nodePath.split(`node-gyp-bin${pathSeparator}`).pop();
}

/**
* Checks for the absence of global gulp, and the presence of gulp-cli and local
* gulp.
*/
function runGulpChecks() {
const firstInstall = !fs.existsSync('node_modules');
const globalPackages = getStdout('npm list --global --depth 0').trim();
const globalGulp = globalPackages.match(/gulp@.*/);
const globalGulpCli = globalPackages.match(/gulp-cli@.*/);
const defaultGulpPath = getStdout('which gulp', {
'env': {'PATH': getParentShellPath()},
}).trim();
const wrongGulp = wrongGulpPaths.some((path) =>
defaultGulpPath.startsWith(path)
);
if (globalGulp) {
console.log(
yellow('WARNING: Detected a global install of'),
cyan('gulp') + yellow('. It is recommended that you use'),
cyan('gulp-cli'),
yellow('instead.')
);
console.log(
yellow('⤷ To fix this, run'),
cyan('"npm uninstall --global gulp"'),
yellow('followed by'),
cyan('"npm install --global gulp-cli"') + yellow('.')
);
console.log(
yellow('⤷ See'),
cyan(gulpHelpUrl),
yellow('for more information.')
);
updatesNeeded.add('gulp');
} else if (!globalGulpCli) {
const whichGulp = getStdout('which gulp').trim();
if (!whichGulp.match(/\/gulp/)) {
// User is missing a global gulp install on a terminal supporting `which`.
// Or they do not have it installed via NPM.
console.log(
yellow('WARNING: Could not find a global install of'),
cyan('gulp-cli') + yellow('.')
);
console.log(
yellow('⤷ To fix this, run'),
cyan('"npm install --global gulp-cli"') + yellow('.')
);
updatesNeeded.add('gulp-cli');
}
} else {
printGulpVersion('gulp-cli');
}
if (wrongGulp) {
console.log(
yellow('WARNING: Found'),
cyan('gulp'),
yellow('in an unexpected location:'),
cyan(defaultGulpPath) + yellow('.')
);
console.log(
yellow('⤷ To fix this, consider removing'),
cyan(defaultGulpPath),
yellow('from your default'),
cyan('$PATH') + yellow(', or deleting it.')
);
console.log(
yellow('⤷ Run'),
cyan('"which gulp"'),
yellow('for more information.')
);
updatesNeeded.add('gulp');
}
if (!firstInstall) {
printGulpVersion('gulp');
}
}

/**
* Prints version info for the given gulp command
*
* @param {string} gulpCmd
*/
function printGulpVersion(gulpCmd) {
const versionRegex =
gulpCmd == 'gulp' ? /Local version[:]? (.*?)$/ : /^CLI version[:]? (.*?)\n/;
const gulpVersions = getStdout('gulp --version').trim();
const gulpVersion = gulpVersions.match(versionRegex);
if (gulpVersion && gulpVersion.length == 2) {
console.log(
green('Detected'),
cyan(gulpCmd),
green('version'),
cyan(gulpVersion[1]) + green('.')
);
} else {
console.log(
yellow(`WARNING: Could not determine the version of ${gulpCmd}.`)
);
}
}

/**
* Checks if the local version of python is 2.7 or 3
*/
Expand Down Expand Up @@ -394,7 +268,6 @@ function checkPythonVersion() {
async function main() {
ensureNpm();
await checkNodeVersion();
runGulpChecks();
checkPythonVersion();
logNpmVersion();
if (updatesNeeded.size) {
Expand Down
Loading