diff --git a/bin/kuduscript.js b/bin/kuduscript.js index 71a981a..278b5af 100644 --- a/bin/kuduscript.js +++ b/bin/kuduscript.js @@ -15,6 +15,7 @@ function addDeploymentScriptOptions(command) { .option('--aspWebSite', 'Create a deployment script for basic website') .option('--go', 'Create a deployment script for Go website') .option('--node', 'Create a deployment script for node.js website') + .option('--angular', 'Create a deployment script for angular website') .option('--ruby', 'Create a deployment script for ruby website') .option('--php', 'Create a deployment script for php website') .option('--python', 'Create a deployment script for python website') @@ -46,7 +47,7 @@ function deploymentScriptExecute(name, options, log, confirm, _) { var noDotDeployment = options.dotDeployment === false; var noSolution = options.solution === false; - var exclusionFlags = [options.aspWAP, options.php, options.python, options.aspWebSite, options.node, options.ruby, options.basic, options.functionApp, options.dotNetConsole, options.aspNetCore, options.go]; + var exclusionFlags = [options.aspWAP, options.php, options.python, options.aspWebSite, options.node, options.angular, options.ruby, options.basic, options.functionApp, options.dotNetConsole, options.aspNetCore, options.go]; var flagCount = 0; for (var i in exclusionFlags) { if (exclusionFlags[i]) { @@ -57,10 +58,10 @@ function deploymentScriptExecute(name, options, log, confirm, _) { if (flagCount === 0) { options.helpInformation(); log.help(''); - log.help('Please specify one of these flags: --aspWAP, --aspNetCore, --aspWebSite, --php, --python, --dotNetConsole, --basic, --ruby, --functionApp or --node'); + log.help('Please specify one of these flags: --angular --aspWAP, --aspNetCore, --aspWebSite, --php, --python, --dotNetConsole, --basic, --ruby, --functionApp or --node'); return; } else if (flagCount > 1) { - throw new Error('Please specify only one of these flags: --aspWAP, --aspNetCore, --aspWebSite, --php, --python, --dotNetConsole, --basic, --ruby, --functionApp or --node'); + throw new Error('Please specify only one of these flags: --angular --aspWAP, --aspNetCore, --aspWebSite, --php, --python, --dotNetConsole, --basic, --ruby, --functionApp or --node'); } var projectType; @@ -73,7 +74,9 @@ function deploymentScriptExecute(name, options, log, confirm, _) { }else if (options.go) { projectType = generator.ProjectType.go; } else if (options.node) { - projectType = generator.ProjectType.node; + projectType = generator.ProjectType.node; + } else if (options.angular) { + projectType = generator.ProjectType.angular; } else if (options.python) { projectType = generator.ProjectType.python; } else if (options.dotNetConsole) { diff --git a/lib/generator._js b/lib/generator._js index bfacc45..8bdc37f 100644 --- a/lib/generator._js +++ b/lib/generator._js @@ -38,6 +38,7 @@ var ProjectType = { wap: 'WAP', website: 'WEBSITE', node: 'NODE', + angular: 'ANGULAR', python: 'PYTHON', basic: 'BASIC', functionApp: 'FUNCTIONAPP', @@ -123,6 +124,7 @@ function ScriptGenerator(repositoryRoot, projectType, projectPath, solutionPath, this.generators[ProjectType.wap] = generateWapDeploymentScript; this.generators[ProjectType.website] = generateWebSiteDeploymentScript; this.generators[ProjectType.node] = generateNodeDeploymentScript; + this.generators[ProjectType.angular] = generateAngularDeploymentScript; this.generators[ProjectType.python] = generatePythonDeploymentScript; this.generators[ProjectType.basic] = generateBasicWebSiteDeploymentScript; this.generators[ProjectType.functionApp] = generateFunctionAppDeploymentScript; @@ -157,6 +159,10 @@ function generateNodeDeploymentScript(scriptGenerator, _) { scriptGenerator.generateNodeDeploymentScript(_); } +function generateAngularDeploymentScript(scriptGenerator, _) { + scriptGenerator.generateAngularDeploymentScript(_); +} + function generatePythonDeploymentScript(scriptGenerator, _) { scriptGenerator.generatePythonDeploymentScript(_); } @@ -211,6 +217,12 @@ ScriptGenerator.prototype.generateNodeDeploymentScript = function (_) { this.generateBasicDeploymentScript('node.template', _); }; +ScriptGenerator.prototype.generateAngularDeploymentScript = function (_) { + log.info('Generating deployment script for Angular Web Site'); + + this.generateBasicDeploymentScript('angular.template', _); +}; + ScriptGenerator.prototype.generateFunctionAppDeploymentScript = function(_) { log.info('Generating deployment script for function App'); diff --git a/lib/generator.js b/lib/generator.js index 750cc4a..67ee4dc 100644 --- a/lib/generator.js +++ b/lib/generator.js @@ -38,6 +38,7 @@ var ProjectType = { wap: "WAP", website: "WEBSITE", node: "NODE", + angular: "ANGULAR", python: "PYTHON", basic: "BASIC", functionApp: "FUNCTIONAPP", @@ -123,6 +124,7 @@ function ScriptGenerator(repositoryRoot, projectType, projectPath, solutionPath, this.generators[ProjectType.wap] = generateWapDeploymentScript; this.generators[ProjectType.website] = generateWebSiteDeploymentScript; this.generators[ProjectType.node] = generateNodeDeploymentScript; + this.generators[ProjectType.angular] = generateAngularDeploymentScript; this.generators[ProjectType.python] = generatePythonDeploymentScript; this.generators[ProjectType.basic] = generateBasicWebSiteDeploymentScript; this.generators[ProjectType.functionApp] = generateFunctionAppDeploymentScript; @@ -157,6 +159,13 @@ function generateNodeDeploymentScript(scriptGenerator, _) { var __frame = { name return scriptGenerator.generateNodeDeploymentScript(__cb(_, __frame, 1, 2, _, true)); });}; +function generateAngularDeploymentScript(scriptGenerator, _) { + var __frame = { name: "generateAngularDeploymentScript", line: 156 }; + return __func(_, this, arguments, generateAngularDeploymentScript, 1, __frame, + function __$generateAngularDeploymentScript() { + return scriptGenerator.generateAngularDeploymentScript(__cb(_, __frame, 1, 2, _, true)); });}; + + function generatePythonDeploymentScript(scriptGenerator, _) { var __frame = { name: "generatePythonDeploymentScript", line: 160 }; return __func(_, this, arguments, generatePythonDeploymentScript, 1, __frame, function __$generatePythonDeploymentScript() { return scriptGenerator.generatePythonDeploymentScript(__cb(_, __frame, 1, 2, _, true)); });}; @@ -211,6 +220,18 @@ ScriptGenerator.prototype.generateNodeDeploymentScript = function ScriptGenerato return __this.generateBasicDeploymentScript("node.template", __cb(_, __frame, 3, 2, _, true)); });}; +ScriptGenerator.prototype.generateAngularDeploymentScript = + function ScriptGenerator_prototype_generateAngularDeploymentScript__3(_) { + var __this = this; var __frame = { name: "ScriptGenerator_prototype_generateAngularDeploymentScript__3", + line: 208 + }; + return __func(_, this, arguments, ScriptGenerator_prototype_generateAngularDeploymentScript__3, 0, __frame, + function __$ScriptGenerator_prototype_generateAngularDeploymentScript__3() { + log.info("Generating deployment script for angular Web Site"); + + return __this.generateBasicDeploymentScript("angular.template", __cb(_, __frame, 3, 2, _, true)); });}; + + ScriptGenerator.prototype.generateFunctionAppDeploymentScript = function ScriptGenerator_prototype_generateFunctionAppDeploymentScript__4(_) { var __this = this; var __frame = { name: "ScriptGenerator_prototype_generateFunctionAppDeploymentScript__4", line: 214 }; return __func(_, this, arguments, ScriptGenerator_prototype_generateFunctionAppDeploymentScript__4, 0, __frame, function __$ScriptGenerator_prototype_generateFunctionAppDeploymentScript__4() { log.info("Generating deployment script for function App"); diff --git a/lib/templates/deploy.bash.angular.template b/lib/templates/deploy.bash.angular.template new file mode 100644 index 0000000..b98d313 --- /dev/null +++ b/lib/templates/deploy.bash.angular.template @@ -0,0 +1,59 @@ +# Node Helpers +# ------------ + +selectNodeVersion () { + if [[ -n "$KUDU_SELECT_NODE_VERSION_CMD" ]]; then + SELECT_NODE_VERSION="$KUDU_SELECT_NODE_VERSION_CMD \"$DEPLOYMENT_SOURCE{SitePath}\" \"$DEPLOYMENT_TARGET\" \"$DEPLOYMENT_TEMP\"" + eval $SELECT_NODE_VERSION + exitWithMessageOnError "select node version failed" + + if [[ -e "$DEPLOYMENT_TEMP/__nodeVersion.tmp" ]]; then + NODE_EXE=`cat "$DEPLOYMENT_TEMP/__nodeVersion.tmp"` + exitWithMessageOnError "getting node version failed" + fi + + if [[ -e "$DEPLOYMENT_TEMP/__npmVersion.tmp" ]]; then + NPM_JS_PATH=`cat "$DEPLOYMENT_TEMP/__npmVersion.tmp"` + exitWithMessageOnError "getting npm version failed" + fi + + if [[ ! -n "$NODE_EXE" ]]; then + NODE_EXE=node + fi + + NPM_CMD="\"$NODE_EXE\" \"$NPM_JS_PATH\"" + else + NPM_CMD=npm + NODE_EXE=node + fi +} + +################################################################################################################################## +# Deployment +# ---------- + +echo Handling Angular deployment. + +# 1. KuduSync +if [[ "$IN_PLACE_DEPLOYMENT" -ne "1" ]]; then + "$KUDU_SYNC_CMD" -v 50 -f "$DEPLOYMENT_SOURCE{SitePath}" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh" + exitWithMessageOnError "Kudu Sync failed" +fi + +# 2. Select node version +selectNodeVersion + +# 3. Install npm packages and angular +if [ -e "$DEPLOYMENT_TARGET/package.json" ]; then + cd "$DEPLOYMENT_TARGET" + eval $NPM_CMD build --prod --env=prod --aot + rm -rf ./{e2e,src} + cp ./web.config ./dist/web.config + + exitWithMessageOnError "npm Angular failed" + cd - > /dev/null +fi + +echo "!!!! Remember to set site root to 'site\wwwroot\dist' !!!!" + +################################################################################################################################## diff --git a/lib/templates/deploy.batch.angular.template b/lib/templates/deploy.batch.angular.template new file mode 100644 index 0000000..bd5ca85 --- /dev/null +++ b/lib/templates/deploy.batch.angular.template @@ -0,0 +1,72 @@ +goto Deployment + +:: Utility Functions +:: ----------------- + +:SelectNodeVersion + +IF DEFINED KUDU_SELECT_NODE_VERSION_CMD ( + :: The following are done only on Windows Azure Websites environment + call %KUDU_SELECT_NODE_VERSION_CMD% "%DEPLOYMENT_SOURCE%{SitePath}" "%DEPLOYMENT_TARGET%" "%DEPLOYMENT_TEMP%" + IF !ERRORLEVEL! NEQ 0 goto error + + IF EXIST "%DEPLOYMENT_TEMP%\__nodeVersion.tmp" ( + SET /p NODE_EXE=<"%DEPLOYMENT_TEMP%\__nodeVersion.tmp" + IF !ERRORLEVEL! NEQ 0 goto error + ) + + IF EXIST "%DEPLOYMENT_TEMP%\__npmVersion.tmp" ( + SET /p NPM_JS_PATH=<"%DEPLOYMENT_TEMP%\__npmVersion.tmp" + IF !ERRORLEVEL! NEQ 0 goto error + ) + + IF NOT DEFINED NODE_EXE ( + SET NODE_EXE=node + ) + + SET NPM_CMD="!NODE_EXE!" "!NPM_JS_PATH!" +) ELSE ( + SET NPM_CMD=npm + SET NODE_EXE=node +) + +goto :EOF + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: Deployment +:: ---------- + +:Deployment +echo Handling node.js deployment. + +:: 1. KuduSync +IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" ( + call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_SOURCE%{SitePath}" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd" + IF !ERRORLEVEL! NEQ 0 goto error +) + +:: 2. Select node version +call :SelectNodeVersion + +:: 3. Install npm packages +IF EXIST "%DEPLOYMENT_TARGET%\package.json" ( + pushd "%DEPLOYMENT_TARGET%" + call :ExecuteCmd !NPM_CMD! install --production + IF !ERRORLEVEL! NEQ 0 goto error + popd +) + +echo Handling Angular build +:: 4. Build ng app +IF EXIST "%DEPLOYMENT_TARGET%\package.json" ( + pushd "%DEPLOYMENT_TARGET%" + call :ExecuteCmd "!NODE_EXE!" ./node_modules/@angular/cli/bin/ng build --prod --env=prod --aot + :: the next line is optional to fix 404 error see section #8 + call :ExecuteCmd cp "%DEPLOYMENT_TARGET%"\web.config "%DEPLOYMENT_TARGET%"\dist\ + IF !ERRORLEVEL! NEQ 0 goto error + popd +) + +echo !!!! Remember to set site root to 'site\wwwroot\dist' !!!! + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/lib/templates/deploy.posh.angular.template b/lib/templates/deploy.posh.angular.template new file mode 100644 index 0000000..97effdd --- /dev/null +++ b/lib/templates/deploy.posh.angular.template @@ -0,0 +1,64 @@ + +# Node Helpers +# ------------ + +$NODE_EXE = "node" +$NPM_CMD = "npm" + +function selectNodeVersion() { + if ($env:KUDU_SELECT_NODE_VERSION_CMD -ne $null) { + # The following are done only on Windows Azure Websites environment + $SELECT_NODE_VERSION = "$env:KUDU_SELECT_NODE_VERSION_CMD `"$DEPLOYMENT_SOURCE{SitePath}`" `"$DEPLOYMENT_TARGET`" `"$DEPLOYMENT_TEMP`"" + try { + iex $SELECT_NODE_VERSION + } catch { + exitWithMessageOnError "select node version failed" + } + + if (Test-Path "$DEPLOYMENT_TEMP\__nodeVersion.tmp") { + $NODE_EXE = cat "$DEPLOYMENT_TEMP\__nodeVersion.tmp" + exitWithMessageOnError "getting node version failed" + } + + if (Test-Path "$DEPLOYMENT_TEMP\__npmVersion.tmp") { + $NPM_JS_PATH = cat "$DEPLOYMENT_TEMP\__npmVersion.tmp" + exitWithMessageOnError "getting npm version failed" + } + + if ($NODE_EXE -eq $null) { + $NODE_EXE = "node" + } + $NPM_CMD = "`"$NODE_EXE`" `"$NPM_JS_PATH`"" + } +} + +################################################################################################################################## +# Deployment +# ---------- + +echo "Handling node.js deployment." + +# 1. KuduSync +if ($env:IN_PLACE_DEPLOYMENT -ne "1") { + & $KUDU_SYNC_CMD -v 50 -f "$DEPLOYMENT_SOURCE{SitePath}" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.ps1" + exitWithMessageOnError "Kudu Sync failed" +} + +# 2. Select node version +selectNodeVersion + +# 3. Install npm packages and angular +if (Test-Path "$DEPLOYMENT_TARGET\package.json") { + pushd "$DEPLOYMENT_TARGET" + try { + iex "$NPM_CMD build --prod --env=prod --aot" + } catch { + exitWithMessageOnError "npm failed" + } + Copy-Item "$DEPLOYMENT_TARGET\web.config" "$DEPLOYMENT_TARGET\dist\web.config" + popd +} + +echo "!!!! Remember to set site root to 'site\wwwroot\dist' !!!!" + +################################################################################################################################## diff --git a/test/smokeTest.js b/test/smokeTest.js index 0c8625e..1e26f89 100644 --- a/test/smokeTest.js +++ b/test/smokeTest.js @@ -31,6 +31,11 @@ suite('Kudu Script Smoke Tests', function () { var scriptType = ScriptType.batch; runScenario("--node", scriptType, done); }); + test('Angular generated batch script runs without a failure', function (done) { + generateFile(pathUtil.join(testDir, "server.js"), "content"); + var scriptType = ScriptType.batch; + runScenario("--angular", scriptType, done); + }); test('Python generated batch script runs without a failure', function (done) { generateFile(pathUtil.join(testDir, "app.py"), "content"); @@ -49,6 +54,11 @@ suite('Kudu Script Smoke Tests', function () { var scriptType = ScriptType.bash; runScenario("--node", scriptType, done); }); + test('Angular generated bash script runs without a failure', function (done) { + generateFile(pathUtil.join(testDir, "server.js"), "content"); + var scriptType = ScriptType.bash; + runScenario("--angular", scriptType, done); + }); test('PHP generated bash script runs without a failure', function (done) { generateFile(pathUtil.join(testDir, "composer.json"), "content"); @@ -68,6 +78,12 @@ suite('Kudu Script Smoke Tests', function () { runScenario("--node", scriptType, done); }); + test('Angular generated posh script runs without a failure', function (done) { + generateFile(pathUtil.join(testDir, "server.js"), "content"); + var scriptType = ScriptType.posh; + runScenario("--angular", scriptType, done); + }); + setup(function () { // Setting a different test directory per test. incrementTestDir();