nativescript-starter-kits/Gruntfile.js

253 строки
9.4 KiB
JavaScript

"use strict";
const path = require("path");
const fs = require("fs");
const childProcess = require("child_process");
const _ = require("lodash");
const os = require("os");
const nodeArgs = [];
const getBuildVersion = (version) => {
let buildVersion = version !== undefined ? version : process.env["BUILD_NUMBER"];
if (process.env["BUILD_CAUSE_GHPRBCAUSE"]) {
buildVersion = "PR" + buildVersion;
}
return buildVersion;
};
module.exports = function (grunt) {
// Windows cmd does not accept paths with / and unix shell does not accept paths with \\ and we need to execute from a sub-dir.
// To circumvent the issue, hack our environment's PATH and let the OS deal with it, which in practice works
process.env.path = process.env.path + (os.platform() === "win32" ? ";" : ":") + "node_modules/.bin";
const defaultEnvironment = "sit";
grunt.initConfig({
deploymentEnvironment: process.env["DeploymentEnvironment"] || defaultEnvironment,
resourceDownloadEnvironment: process.env["ResourceDownloadEnvironment"] || defaultEnvironment,
jobName: process.env["JOB_NAME"] || defaultEnvironment,
buildNumber: process.env["BUILD_NUMBER"] || "non-ci",
pkg: grunt.file.readJSON("package.json"),
ts: {
options: grunt.file.readJSON("tsconfig.json").compilerOptions,
devlib: {
src: ["lib/**/*.ts", "test/**/*.ts", "references.d.ts", "!node_modules/**/*", "!lib/templates/**/*.ts"]
},
release_build: {
src: ["lib/**/*.ts", "test/**/*.ts", "references.d.ts", "!node_modules/**/*", "!lib/templates/**/*.ts"],
options: {
sourceMap: false,
removeComments: true
}
}
},
tslint: {
build: {
files: {
src: ["lib/**/*.ts", "test/**/*.ts", "definitions/**/*.ts", "!lib/templates/**/*.ts"]
},
options: {
configuration: grunt.file.readJSON("./tslint.json")
}
}
},
watch: {
devall: {
files: ["lib/**/*.ts", "test/**/*.ts"],
tasks: ['ts:devlib'],
options: {
atBegin: true,
interrupt: true
}
}
},
shell: {
options: {
stdout: true,
stderr: true
},
ci_unit_tests: {
command: "npm test",
options: {
execOptions: {
env: (function () {
let env = _.cloneDeep(process.env);
env["XUNIT_FILE"] = "test-reports.xml";
env["LOG_XUNIT"] = "true";
return env;
})()
}
}
},
apply_deployment_environment: {
command: "node " + nodeArgs.join(" ") + " bin/appbuilder dev-config-apply <%= deploymentEnvironment %>"
},
build_package: {
command: "npm pack",
options: {
execOptions: {
env: (function () {
let env = _.cloneDeep(process.env);
env["APPBUILDER_SKIP_POSTINSTALL_TASKS"] = "1";
return env;
})()
}
}
}
},
clean: {
src: ["test/**/*.js*",
"lib/**/*.js*",
"*.tgz"]
}
});
grunt.loadNpmTasks("grunt-contrib-clean");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks("grunt-shell");
grunt.loadNpmTasks("grunt-ts");
grunt.loadNpmTasks("grunt-tslint");
grunt.registerTask("set_package_version", function (version) {
const buildVersion = getBuildVersion(version);
const packageJson = grunt.file.readJSON("package.json");
packageJson.buildVersion = buildVersion;
grunt.file.write("package.json", JSON.stringify(packageJson, null, " "));
});
const transpileProject = function (dirname) {
const pathToModule = path.join(__dirname, "node_modules", dirname);
const packageJsonContent = grunt.file.readJSON(path.join(pathToModule, "package.json"));
try {
// Keep the --production flag - in case we skip it, we'll instal istanbul, chai, etc. and their .d.ts will conflict with ours.
childProcess.execSync("npm i --ignore-scripts --production", { cwd: pathToModule, stdio: "ignore" });
} catch (err) {
}
try {
// grunt deps must be installed locally in the project where grunt will be called.
// also for transpilation we need typescript locally.
const searchedNames = ["grunt", "typescript"];
const dependenciesToInstall = _.map(packageJsonContent.devDependencies, (version, name) => {
for (let searchedName of searchedNames) {
if (name.indexOf(searchedName) !== -1 && !fs.existsSync(path.join(pathToModule, "node_modules", name))) {
return `${name}@${version}`
}
}
}).filter(a => !!a);
_.each(dependenciesToInstall, name => {
try {
childProcess.execSync(`npm i --ignore-scripts --production ${name}`, { cwd: pathToModule, stdio: "ignore" });
} catch (err) {
}
})
} catch (err) { }
try {
// we need the .js file in the tests, so we can require them, for example in order to create a new instance of injector.
// if the main file is .js and it exists, no need to transpile it again
const pathToMain = path.join(pathToModule, packageJsonContent.main);
if (!fs.existsSync(pathToMain)) {
childProcess.execSync("grunt", { cwd: pathToModule, stdio: "ignore" });
}
} catch (err) { }
};
grunt.registerTask("transpile_additional_project", function () {
transpileProject("nativescript");
transpileProject("mobile-cli-lib");
transpileProject("ios-device-lib");
});
grunt.registerTask("setPackageName", function (version) {
const fs = require("fs");
const fileExtension = ".tgz";
const buildVersion = getBuildVersion(version);
const packageJson = grunt.file.readJSON("package.json");
const oldFileName = packageJson.name + "-" + packageJson.version;
const newFileName = oldFileName + "-" + buildVersion;
fs.renameSync(oldFileName + fileExtension, newFileName + fileExtension);
});
grunt.registerTask("delete_coverage_dir", function () {
const done = this.async();
const rimraf = require("rimraf");
rimraf("coverage", function (err) {
if (err) {
console.log("Error while deleting coverage directory from the package.");
done(false);
}
done();
});
});
grunt.registerTask("test", ["transpile_additional_project", "generate_references", "ts:devlib"]);
grunt.registerTask("generate_references", () => {
const referencesPath = path.join(__dirname, "references.d.ts");
// get all .d.ts files from nativescript-cli and mobile-cli-lib
const nodeModulesDirPath = path.join(__dirname, "node_modules");
let pathsOfDtsFiles = getReferencesFromDir(path.join(nodeModulesDirPath, "nativescript"))
.concat(getReferencesFromDir(path.join(nodeModulesDirPath, "mobile-cli-lib")))
.concat(getReferencesFromDir(path.join(nodeModulesDirPath, "ios-device-lib")));
const lines = pathsOfDtsFiles.map(file => `/// <reference path="${fromWindowsRelativePathToUnix(path.relative(__dirname, file))}" />`);
fs.writeFileSync(referencesPath, lines.join(os.EOL));
});
const fromWindowsRelativePathToUnix = (windowsRelativePath) => {
return windowsRelativePath.replace(/\\/g, "/");
};
// returns paths that have to be added to reference.d.ts.
const getReferencesFromDir = (dir) => {
const currentDirContent = fs.readdirSync(dir).map(item => path.join(dir, item));
let pathsToDtsFiles = [];
_.each(currentDirContent, d => {
const stat = fs.statSync(d);
if (stat.isDirectory() && path.basename(d) !== "node_modules") {
// recursively check all dirs for .d.ts files.
pathsToDtsFiles = pathsToDtsFiles.concat(getReferencesFromDir(d));
} else if (stat.isFile() && d.endsWith(".d.ts") && path.basename(d) !== ".d.ts") {
pathsToDtsFiles.push(d);
}
});
return pathsToDtsFiles;
};
grunt.registerTask("pack", [
"clean",
"generate_references",
"ts:release_build",
"transpile_additional_project",
"tslint:build",
"set_package_version",
"delete_coverage_dir",
"shell:build_package",
"setPackageName"
]);
grunt.registerTask("lint", ["tslint:build"]);
grunt.registerTask("all", ["clean", "test", "lint"]);
grunt.registerTask("rebuild", ["clean", "ts:devlib"]);
grunt.registerTask("default", ["generate_references", "ts:devlib"]);
};