mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-08-31 01:02:04 +08:00
231 lines
8.2 KiB
JavaScript
231 lines
8.2 KiB
JavaScript
const path = require("path");
|
|
const fs = require("fs");
|
|
const del = require("del");
|
|
const { src, dest, series, parallel, watch } = require("gulp");
|
|
const child_process = require("child_process");
|
|
const { globSync } = require("glob");
|
|
const buildIcons = require("./icons/build_icons");
|
|
|
|
/*
|
|
* We'll want a flexible glob down the road, but for now there are no
|
|
* un-built visualizations in the repository; for performance and
|
|
* simplicity just add them one at a time until we upgrade older viz's.
|
|
*/
|
|
const STATIC_PLUGIN_BUILD_IDS = [
|
|
"annotate_image",
|
|
"chiraviz",
|
|
"cytoscape",
|
|
"drawrna",
|
|
"editor",
|
|
"example",
|
|
"fits_image_viewer",
|
|
"h5web",
|
|
"heatmap/heatmap_default",
|
|
"hyphyvision",
|
|
"jqplot/jqplot_bar",
|
|
"media_player",
|
|
"msa",
|
|
"mvpapp",
|
|
"ngl",
|
|
"nvd3/nvd3_bar",
|
|
"openlayers",
|
|
"openseadragon",
|
|
"PCA_3Dplot",
|
|
"phylocanvas",
|
|
"pv",
|
|
"nora",
|
|
"venn",
|
|
"tiffviewer",
|
|
"ts_visjs",
|
|
];
|
|
const DIST_PLUGIN_BUILD_IDS = ["new_user"];
|
|
const PLUGIN_BUILD_IDS = Array.prototype.concat(DIST_PLUGIN_BUILD_IDS, STATIC_PLUGIN_BUILD_IDS);
|
|
|
|
const PATHS = {
|
|
nodeModules: "./node_modules",
|
|
stagedLibraries: {
|
|
// This is a stepping stone towards having all this staged
|
|
// automatically. Eventually, this dictionary and staging step will
|
|
// not be necessary.
|
|
backbone: ["backbone.js", "backbone.js"],
|
|
jquery: ["dist/jquery.js", "jquery/jquery.js"],
|
|
"jquery-migrate": ["dist/jquery-migrate.js", "jquery/jquery.migrate.js"],
|
|
"jquery-mousewheel": ["jquery.mousewheel.js", "jquery/jquery.mousewheel.js"],
|
|
requirejs: ["require.js", "require.js"],
|
|
underscore: ["underscore.js", "underscore.js"],
|
|
},
|
|
};
|
|
|
|
const failOnError =
|
|
process.env.GALAXY_PLUGIN_BUILD_FAIL_ON_ERROR && process.env.GALAXY_PLUGIN_BUILD_FAIL_ON_ERROR !== "0"
|
|
? true
|
|
: false;
|
|
|
|
PATHS.pluginBaseDir =
|
|
(process.env.GALAXY_PLUGIN_PATH && process.env.GALAXY_PLUGIN_PATH !== "None"
|
|
? process.env.GALAXY_PLUGIN_PATH
|
|
: undefined) || "../config/plugins/";
|
|
|
|
PATHS.pluginDirs = [
|
|
path.join(PATHS.pluginBaseDir, "{visualizations,welcome_page}/*/static/**/*"),
|
|
path.join(PATHS.pluginBaseDir, "{visualizations,welcome_page}/*/*/static/**/*"),
|
|
];
|
|
|
|
PATHS.pluginBuildModules = [
|
|
path.join(PATHS.pluginBaseDir, `{visualizations,welcome_page}/{${PLUGIN_BUILD_IDS.join(",")}}/package.json`),
|
|
];
|
|
|
|
function stageLibs(callback) {
|
|
Object.keys(PATHS.stagedLibraries).forEach((lib) => {
|
|
var p1 = path.resolve(path.join(PATHS.nodeModules, lib, PATHS.stagedLibraries[lib][0]));
|
|
var p2 = path.resolve(path.join("src", "libs", PATHS.stagedLibraries[lib][1]));
|
|
if (fs.existsSync(p1)) {
|
|
del.sync(p2);
|
|
fs.createReadStream(p1).pipe(fs.createWriteStream(p2));
|
|
} else {
|
|
callback(
|
|
p1 +
|
|
" does not exist, yet it is a required library. This is an error. Check that the package in question exists in node_modules."
|
|
);
|
|
}
|
|
});
|
|
return callback();
|
|
}
|
|
|
|
function fonts() {
|
|
return src(path.resolve(path.join(PATHS.nodeModules, "font-awesome/fonts/**/*"))).pipe(
|
|
dest("../static/images/fonts")
|
|
);
|
|
}
|
|
|
|
async function icons() {
|
|
await buildIcons("./src/assets/icons.json");
|
|
}
|
|
|
|
function stagePlugins() {
|
|
return src(PATHS.pluginDirs).pipe(dest("../static/plugins/"));
|
|
}
|
|
|
|
function buildPlugins(callback, forceRebuild) {
|
|
/*
|
|
* Walk pluginBuildModules glob and attempt to build modules.
|
|
* */
|
|
const packageJsons = globSync(PATHS.pluginBuildModules, {});
|
|
packageJsons.forEach((file) => {
|
|
let skipBuild = false;
|
|
const pluginDir = path.dirname(file);
|
|
const pluginName = pluginDir.split(path.sep).pop();
|
|
|
|
const hashFilePath = path.join(
|
|
pluginDir,
|
|
DIST_PLUGIN_BUILD_IDS.indexOf(pluginName) > -1 ? "dist" : "static",
|
|
"plugin_build_hash.txt"
|
|
);
|
|
|
|
if (forceRebuild) {
|
|
skipBuild = false;
|
|
} else {
|
|
if (fs.existsSync(hashFilePath)) {
|
|
const hashFileContent = fs.readFileSync(hashFilePath, "utf8").trim();
|
|
const isHash = /^[0-9a-f]{7,40}$/.test(hashFileContent); // Check for a 7 to 40 character hexadecimal string
|
|
|
|
if (!isHash) {
|
|
console.log(`Hash file for ${pluginName} exists but does not have a valid git hash.`);
|
|
skipBuild = false;
|
|
} else {
|
|
skipBuild =
|
|
child_process.spawnSync("git", ["diff", "--quiet", hashFileContent, "--", pluginDir], {
|
|
stdio: "inherit",
|
|
shell: true,
|
|
}).status === 0;
|
|
}
|
|
|
|
skipBuild =
|
|
child_process.spawnSync("git", ["diff", "--quiet", `$(cat ${hashFilePath})`, "--", pluginDir], {
|
|
stdio: "inherit",
|
|
shell: true,
|
|
}).status === 0;
|
|
if (!skipBuild) {
|
|
// Hash exists and is outdated, triggering a rebuild.
|
|
// Stage current hash to .orig for debugging and to
|
|
// force a plugin rebuild in the event of a failure
|
|
// (i.e. -- we're committed to a new build of this plugin).
|
|
fs.renameSync(hashFilePath, `${hashFilePath}.orig`);
|
|
}
|
|
} else {
|
|
console.log(`No build hashfile detected for ${pluginName}, generating now.`);
|
|
}
|
|
}
|
|
|
|
if (skipBuild) {
|
|
console.log(`No changes detected for ${pluginName}`);
|
|
} else {
|
|
console.log(`Installing Dependencies for ${pluginName}`);
|
|
child_process.spawnSync(
|
|
"yarn",
|
|
["install", "--production=false", "--network-timeout=300000", "--check-files"],
|
|
{
|
|
cwd: pluginDir,
|
|
stdio: "inherit",
|
|
shell: true,
|
|
}
|
|
);
|
|
console.log(`Building ${pluginName}`);
|
|
const opts = {
|
|
cwd: pluginDir,
|
|
stdio: "inherit",
|
|
shell: true,
|
|
};
|
|
// if node version is >16, set NODE_OPTIONS to use legacy openssl provider
|
|
if (process.versions.node.split(".")[0] > "16") {
|
|
opts.env = {
|
|
...process.env,
|
|
PARCEL_WORKER_BACKEND: "process",
|
|
NODE_OPTIONS: "--openssl-legacy-provider",
|
|
};
|
|
}
|
|
if (child_process.spawnSync("yarn", ["build"], opts).status === 0) {
|
|
console.log(`Successfully built, saving build state to ${hashFilePath}`);
|
|
child_process.exec(`(git rev-parse HEAD 2>/dev/null || echo \`\`) > ${hashFilePath}`);
|
|
} else {
|
|
console.error(
|
|
`Error building ${pluginName}, not saving build state. Please report this issue to the Galaxy Team.`
|
|
);
|
|
if (failOnError) {
|
|
// Fail on error.
|
|
console.error(
|
|
"Failing build due to GALAXY_PLUGIN_BUILD_FAIL_ON_ERROR being set, see error(s) above."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return callback();
|
|
}
|
|
|
|
function forceBuildPlugins(callback) {
|
|
return buildPlugins(callback, true);
|
|
}
|
|
|
|
function cleanPlugins() {
|
|
return del(["../static/plugins/{visualizations,welcome_page}/*"], { force: true });
|
|
}
|
|
|
|
const client = parallel(fonts, stageLibs, icons);
|
|
const plugins = series(buildPlugins, cleanPlugins, stagePlugins);
|
|
const pluginsRebuild = series(forceBuildPlugins, cleanPlugins, stagePlugins);
|
|
|
|
function watchPlugins() {
|
|
const BUILD_PLUGIN_WATCH_GLOB = [
|
|
path.join(PATHS.pluginBaseDir, `{visualizations,welcome_page}/{${PLUGIN_BUILD_IDS.join(",")}}/**/*`),
|
|
];
|
|
watch(BUILD_PLUGIN_WATCH_GLOB, { queue: false }, plugins);
|
|
}
|
|
|
|
module.exports.client = client;
|
|
module.exports.plugins = plugins;
|
|
module.exports.pluginsRebuild = pluginsRebuild;
|
|
module.exports.watchPlugins = watchPlugins;
|
|
module.exports.default = parallel(client, plugins);
|