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

feat: Add versioned handler for gulp v5 #265

Merged
merged 1 commit into from Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions lib/versioned/^5.0.0/format-error.js
@@ -0,0 +1,24 @@
'use strict';

// Format orchestrator errors
/* istanbul ignore next */
function formatError(e) {
if (!e.error) {
return e.message;
}

// PluginError
if (typeof e.error.showStack === 'boolean') {
return e.error.toString();
}

// Normal error
if (e.error.stack) {
return e.error.stack;
}

// Unknown (string, number, etc.)
return new Error(String(e.error)).stack;
}

module.exports = formatError;
89 changes: 89 additions & 0 deletions lib/versioned/^5.0.0/index.js
@@ -0,0 +1,89 @@
'use strict';

var fs = require('fs');

var log = require('gulplog');
var stdout = require('mute-stdout');
var messages = require('@gulpjs/messages');

var exit = require('../../shared/exit');

var logTasks = require('../../shared/log/tasks');
var logEvents = require('./log/events');
var logSyncTask = require('./log/sync-task');
var logTasksSimple = require('./log/tasks-simple');
var registerExports = require('../../shared/register-exports');

var copyTree = require('../../shared/log/copy-tree');
var getTask = require('./log/get-task');
var requireOrImport = require('../../shared/require-or-import');

function execute(env, opts, translate) {
var tasks = opts._;
var toRun = tasks.length ? tasks : ['default'];

if (opts.tasksSimple || opts.tasks || opts.tasksJson) {
// Mute stdout if we are listing tasks
stdout.mute();
}

var gulpInst = require(env.modulePath);
logEvents(gulpInst);
logSyncTask(gulpInst, opts);

// This is what actually loads up the gulpfile
requireOrImport(env.configPath, function(err, exported) {
// Before import(), if require() failed we got an unhandled exception on the module level.
// So console.error() & exit() were added here to mimic the old behavior as close as possible.
if (err) {
console.error(err);
exit(1);
}

registerExports(gulpInst, exported);

// Always unmute stdout after gulpfile is required
stdout.unmute();

var tree;
if (opts.tasksSimple) {
tree = gulpInst.tree();
return logTasksSimple(tree.nodes);
}
if (opts.tasks) {
tree = gulpInst.tree({ deep: true });
tree.label = translate.message({ tag: messages.DESCRIPTION, path: env.configPath });

return logTasks(tree, opts, getTask(gulpInst), translate);
}
if (opts.tasksJson) {
tree = gulpInst.tree({ deep: true });
tree.label = translate.message({ tag: messages.DESCRIPTION, path: env.configPath });

var output = JSON.stringify(copyTree(tree, opts));

if (typeof opts.tasksJson === 'boolean' && opts.tasksJson) {
return console.log(output);
}
return fs.writeFileSync(opts.tasksJson, output, 'utf-8');
}
try {
log.info({ tag: messages.GULPFILE, path: env.configPath });
var runMethod = opts.series ? 'series' : 'parallel';
gulpInst[runMethod](toRun)(function(err) {
if (err) {
exit(1);
}
});
} catch (err) {
if (err.task) {
log.error({ tag: messages.TASK_MISSING, task: err.task, similar: err.similar });
} else {
log.error({ tag: messages.EXEC_ERROR, message: err.message, error: err });
}
exit(1);
}
});
}

module.exports = execute;
39 changes: 39 additions & 0 deletions lib/versioned/^5.0.0/log/events.js
@@ -0,0 +1,39 @@
'use strict';

var log = require('gulplog');
var messages = require('@gulpjs/messages');

var formatError = require('../format-error');

// Wire up logging events
function logEvents(gulpInst) {

var loggedErrors = [];

gulpInst.on('start', function(evt) {
/* istanbul ignore next */
// TODO: batch these
// so when 5 tasks start at once it only logs one time with all 5
var level = evt.branch ? 'debug' : 'info';
log[level]({ tag: messages.TASK_START, task: evt.name });
});

gulpInst.on('stop', function(evt) {
/* istanbul ignore next */
var level = evt.branch ? 'debug' : 'info';
log[level]({ tag: messages.TASK_STOP, task: evt.name, duration: evt.duration });
});

gulpInst.on('error', function(evt) {
var level = evt.branch ? 'debug' : 'error';
log[level]({ tag: messages.TASK_FAILURE, task: evt.name, duration: evt.duration });

// If we haven't logged this before, log it and add to list
if (loggedErrors.indexOf(evt.error) === -1) {
log.error({ tag: messages.TASK_ERROR, message: formatError(evt) });
loggedErrors.push(evt.error);
}
});
}

module.exports = logEvents;
43 changes: 43 additions & 0 deletions lib/versioned/^5.0.0/log/get-task.js
@@ -0,0 +1,43 @@
'use strict';

var isObject = require('../../../shared/is-object');

function getTask(gulpInst) {
return function(name) {
var task = gulpInst.task(name);
return {
description: getDescription(task),
flags: getFlags(task),
};
};
}

function getDescription(task) {
if (typeof task.description === 'string') {
return task.description;
}
/* istanbul ignore else */
if (typeof task.unwrap === 'function') {
var origFn = task.unwrap();
if (typeof origFn.description === 'string') {
return origFn.description;
}
}
return undefined;
}

function getFlags(task) {
if (isObject(task.flags)) {
return task.flags;
}
/* istanbul ignore else */
if (typeof task.unwrap === 'function') {
var origFn = task.unwrap();
if (isObject(origFn.flags)) {
return origFn.flags;
}
}
return undefined;
}

module.exports = getTask;
46 changes: 46 additions & 0 deletions lib/versioned/^5.0.0/log/sync-task.js
@@ -0,0 +1,46 @@
'use strict';

var log = require('gulplog');
var messages = require('@gulpjs/messages');

var tasks = {};

function warn() {
var taskKeys = Object.keys(tasks);

if (!taskKeys.length) {
return;
}

var taskNames = taskKeys.map(function(key) {
return tasks[key];
}).join(', ');

process.exitCode = 1;

log.warn({ tag: messages.TASK_SYNC, tasks: taskNames });
}

function start(e) {
tasks[e.uid] = e.name;
}

function clear(e) {
delete tasks[e.uid];
}

function clearAll() {
tasks = {};
}

function logSyncTask(gulpInst, opts) {

process.once('exit', warn);
gulpInst.on('start', start);
gulpInst.on('stop', clear);
// When not running in --continue mode, we need to clear everything on error to avoid
// false positives.
gulpInst.on('error', opts.continue ? clear : clearAll);
}

module.exports = logSyncTask;
7 changes: 7 additions & 0 deletions lib/versioned/^5.0.0/log/tasks-simple.js
@@ -0,0 +1,7 @@
'use strict';

function logTasksSimple(nodes) {
console.log(nodes.join('\n').trim());
}

module.exports = logTasksSimple;