mybuddy/gulpfile.js

417 lines
9.3 KiB
JavaScript

const gulp = require("gulp");
const all = require("gulp-all");
const concat = require("gulp-concat");
const del = require("del");
const es = require("child_process").execSync;
const flatten = require("gulp-flatten");
const fontello = require("gulp-fontello");
const minify = require("gulp-minify");
const removeSourcemaps = require("gulp-remove-sourcemaps");
const sass = require("gulp-sass")(require("sass"));
const sassGlob = require("gulp-sass-glob");
const styleLint = require("@ronilaukkarinen/gulp-stylelint");
const spawn = require("child_process").spawn;
const config = require("./gulpfile.config.js");
/**
* Spawns a command for pipenv.
*
* @param command
* Command and arguments.
*
* @returns {Promise<unknown>}
*
* @private
*/
function _runInPipenv(command) {
command.unshift("run");
command = command.concat(process.argv.splice(3));
return new Promise((resolve, reject) => {
spawn("pipenv", command, { stdio: "inherit" }).on("exit", function (code) {
if (code) {
reject();
}
resolve();
});
});
}
/**
* Run Command
*
* @param command
* Command and arguments.
*
* @returns {Promise<unknown>}
*
* @private
*/
function _runCommand(program, command) {
return new Promise((resolve, reject) => {
spawn(program, command, { stdio: "inherit" }).on("exit", function (code) {
if (code) {
reject();
}
resolve();
});
});
}
/**
* Deletes local static files.
*
* @returns {*}
*/
function clean() {
return del(["**/static", "static"]);
}
/**
* Runs coverage operations.
*
* @param cb
*/
function coverage(cb) {
// Erase any previous coverage results.
es("pipenv run coverage erase", { stdio: "inherit" });
// Run tests with coverage.
spawn(
"pipenv",
[
"run",
"coverage",
"run",
"manage.py",
"test",
"--settings=babybuddy.settings.test",
"--parallel",
"--exclude-tag",
"isolate",
],
{
stdio: "inherit",
},
).on("exit", function (code) {
// Run isolated tests with coverage.
if (code === 0) {
try {
config.testsConfig.isolated.forEach(function (test_name) {
es(
"pipenv run coverage run manage.py test --settings=babybuddy.settings.test " +
test_name,
{ stdio: "inherit" },
);
});
} catch (error) {
console.error(error);
cb();
process.exit(1);
}
// Combine coverage results.
es("pipenv run coverage combine", { stdio: "inherit" });
}
cb();
process.exit(code);
});
}
/**
* Builds the documentation site locally.
*/
function docsBuild() {
return _runInPipenv(["mkdocs", "build"]);
}
/**
* Deploys the documentation site to GitHub Pages.
*/
function docsDeploy() {
return _runInPipenv(["mkdocs", "gh-deploy"]);
}
/**
* Serves the documentation site, watching for changes.
*/
function docsWatch() {
return _runInPipenv(["mkdocs", "serve"]);
}
/**
* Builds and copies "extra" static files to configured paths.
*/
function extras() {
return all(
gulp
.src(config.extrasConfig.fonts.files)
.pipe(gulp.dest(config.extrasConfig.fonts.dest)),
gulp
.src(config.extrasConfig.images.files)
.pipe(flatten({ subPath: 3 }))
.pipe(gulp.dest(config.extrasConfig.images.dest)),
gulp
.src(config.extrasConfig.logo.files)
.pipe(flatten({ subPath: 3 }))
.pipe(gulp.dest(config.extrasConfig.logo.dest)),
gulp
.src(config.extrasConfig.root.files)
.pipe(gulp.dest(config.extrasConfig.root.dest)),
);
}
/**
* Runs Black formatting on Python code.
*/
function format() {
return all(
_runInPipenv(["black", "."]),
_runInPipenv(["djlint", "--reformat", "."]),
_runCommand("npx", ["prettier", ".", "--write"]),
);
}
/**
* Runs linting on Python and SASS code.
*/
function lint() {
return all(
_runInPipenv(["black", ".", "--check", "--diff", "--color"]),
_runInPipenv(["djlint", "--check", "."]),
_runCommand("npx", ["prettier", ".", "--check"]),
gulp.src(config.watchConfig.stylesGlob).pipe(
styleLint({
reporters: [{ formatter: "string", console: true }],
}),
),
);
}
/**
* Builds and copies JavaScript static files to configured paths.
*/
function scripts() {
const streams = [];
const types = ["vendor", "graph", "app", "tags_editor"];
types.forEach((type) => {
streams.push(
gulp
.src(config.scriptsConfig[type])
.pipe(removeSourcemaps())
.pipe(concat(`${type}.js`))
.pipe(
minify({
ext: { min: ".js" },
noSource: true,
}),
)
.pipe(gulp.dest(config.scriptsConfig.dest)),
);
});
return all(streams);
}
/**
* Builds and copies CSS static files to configured paths.
*/
function styles() {
return gulp
.src(config.stylesConfig.app)
.pipe(sassGlob({ ignorePaths: config.stylesConfig.ignore }))
.pipe(sass().on("error", sass.logError))
.pipe(concat("app.css"))
.pipe(gulp.dest(config.stylesConfig.dest));
}
/**
* Runs all tests _not_ tagged "isolate".
*
* @param cb
*/
function test(cb) {
let command = [
"run",
"python",
"-Wa",
"manage.py",
"test",
"--settings=babybuddy.settings.test",
"--parallel",
"--exclude-tag",
"isolate",
];
command = command.concat(process.argv.splice(3));
spawn("pipenv", command, { stdio: "inherit" }).on("exit", function (code) {
if (code === 0) {
// Run isolated tests.
config.testsConfig.isolated.forEach(function (test_name) {
try {
es(
"pipenv run python manage.py test --settings=babybuddy.settings.test " +
test_name,
{ stdio: "inherit" },
);
} catch (error) {
console.error(error);
cb();
process.exit(1);
}
});
}
cb();
process.exit(code);
});
}
/**
* Updates glyphs font data from Fontello.
*/
function updateGlyphs() {
return gulp
.src(config.glyphFontConfig.configFile)
.pipe(fontello({ assetsOnly: false }))
.pipe(gulp.dest(config.glyphFontConfig.dest));
}
/**
* Watches for changes in configured files.
*/
function watch() {
gulp.watch(config.watchConfig.scriptsGlob, scripts);
gulp.watch(config.watchConfig.stylesGlob, styles);
}
/**
* Django management command passthroughs.
*/
gulp.task("collectstatic", function (cb) {
let command = ["run", "python", "manage.py", "collectstatic"];
/* Use base settings if no settings parameter is supplied. */
const parameters = process.argv.splice(3);
let noSettings = true;
for (let i = 0; i < parameters.length; i++) {
if (parameters[i].substring(0, 10) === "--settings") {
noSettings = false;
break;
}
}
if (noSettings) {
parameters.push("--settings=babybuddy.settings.base");
}
command = command.concat(parameters);
spawn("pipenv", command, { stdio: "inherit" }).on("exit", cb);
});
gulp.task("compilemessages", () => {
return _runInPipenv(["python", "manage.py", "compilemessages"]);
});
gulp.task("fake", () => {
return _runInPipenv(["python", "manage.py", "fake"]);
});
gulp.task("migrate", () => {
return _runInPipenv(["python", "manage.py", "migrate"]);
});
gulp.task("makemessages", () => {
return _runInPipenv(["python", "manage.py", "makemessages"]);
});
gulp.task("makemigrations", () => {
return _runInPipenv(["python", "manage.py", "makemigrations"]);
});
gulp.task("reset", () => {
return _runInPipenv(["python", "manage.py", "reset", "--no-input"]);
});
gulp.task("runserver", function (cb) {
let command = ["run", "python", "manage.py", "runserver"];
/**
* Process any parameters. Any arguments found here will be removed from
* the parameters list so other parameters continue to be passed to the
* command.
**/
const parameters = process.argv.splice(2);
for (let i = 0; i < parameters.length; i++) {
/* May be included because this is the default gulp command. */
if (parameters[i] === "runserver") {
delete parameters[i];
} else if (parameters[i] === "--ip") {
/* "--ip" parameter to set the server IP address. */
command.push(parameters[i + 1]);
delete parameters[i];
delete parameters[i + 1];
i++;
}
}
/* Add parameters to command, removing empty values. */
command = command.concat(parameters.filter(String));
spawn("pipenv", command, { stdio: "inherit" }).on("exit", cb);
});
gulp.task("generateschema", () => {
return _runInPipenv([
"python",
"manage.py",
"generateschema",
"--title",
"Baby Buddy API",
"--file",
"openapi-schema.yml",
]);
});
/**
* Gulp commands.
*/
gulp.task("clean", clean);
gulp.task("coverage", coverage);
gulp.task("docs:build", docsBuild);
gulp.task("docs:deploy", docsDeploy);
gulp.task("docs:watch", docsWatch);
gulp.task("extras", extras);
gulp.task("format", format);
gulp.task("lint", lint);
gulp.task("scripts", scripts);
gulp.task("styles", styles);
gulp.task("test", test);
gulp.task("updateglyphs", updateGlyphs);
gulp.task("watch", watch);
/**
* Gulp compound commands.
*/
gulp.task("build", gulp.parallel("extras", "scripts", "styles"));
gulp.task(
"updatestatic",
gulp.series("lint", "clean", "build", "collectstatic"),
);
gulp.task("default", gulp.series("build", gulp.parallel("watch", "runserver")));