cake build angular application to deploy to azure
Asked Answered
A

1

6

I have created a angular application using command ng new APPNAME. I want to use cake build to deploy this application. Is it possible to use cake build? If so how? My end target is to deploy it to azure, but i need to do it with Cake build. I have uploaded all the source code to git repository.

Acheron answered 17/11, 2017 at 6:35 Comment(4)
Could you provide a little more detail? Is is just an Angular app you want to build or does it have a .NET backend / part of a .NET solution?Donalddonaldson
It is just an angular app. Not the part of .net solutionAcheron
you can use cake to copy and deploy the static files after they are build with ng build. I am not familiar with cake but you need to use either the typescript compiler or angular cliOutherod
Yes, but i am new to this. I want to know how it is doneAcheron
D
12

So building a plain vanilla app with the Angular CLI would look something like this

string          target      = Argument("target", "Build");
FilePath        ngPath      = Context.Tools.Resolve("ng.cmd");
FilePath        npmPath     = Context.Tools.Resolve("npm.cmd");
DirectoryPath   outputPath  = MakeAbsolute(Directory("./output"));

Action<FilePath, ProcessArgumentBuilder> Cmd => (path, args) => {
    var result = StartProcess(
        path,
        new ProcessSettings {
            Arguments = args
        });

    if(0 != result)
    {
        throw new Exception($"Failed to execute tool {path.GetFilename()} ({result})");
    }
};

Task("Install-AngularCLI")
    .Does(() => {
    if (ngPath != null && FileExists(ngPath))
    {
        Information("Found Angular CLI at {0}.", ngPath);
        return;
    }

    DirectoryPath ngDirectoryPath = MakeAbsolute(Directory("./Tools/ng"));

    EnsureDirectoryExists(ngDirectoryPath);

    Cmd(npmPath,
        new ProcessArgumentBuilder()
                .Append("install")
                .Append("--prefix")
                .AppendQuoted(ngDirectoryPath.FullPath)
                .Append("@angular/cli")
    );
    ngPath = Context.Tools.Resolve("ng.cmd");
});

Task("Clean")
    .Does( ()=> {
        CleanDirectory(outputPath);
});

Task("Install")
    .IsDependentOn("Clean")
    .Does( ()=> {
    Cmd(npmPath,
        new ProcessArgumentBuilder()
            .Append("install")
    );
});

Task("Build")
    .IsDependentOn("Install-AngularCLI")
    .IsDependentOn("Install")
    .Does( ()=> {
    Cmd(ngPath,
        new ProcessArgumentBuilder()
            .Append("build")
            .Append("--output-path")
            .AppendQuoted(outputPath.FullPath)
    );
});

RunTarget(target);

Which basically does

  1. Install Angular CLI If not found
  2. Install node modules
  3. Build Angular app

If you want to run the build and publish on kudu you can use the Cake.Kudu addin and KuduSync tool, dependencies are declared by adding tool and addin pre-processor directives like this:

#tool nuget:?package=KuduSync.NET&version=1.3.1
#addin nuget:?package=Cake.Kudu&version=0.6.0

And the publish task would look something like this

Task("Publish")
    .IsDependentOn("Build")
    .Does( ()=> {
      Kudu.Sync(outputPath);
});

For kudu to know it should use a custom deployment script you need to add a .deployment file telling it do so, which could look something like this:

[config]
command = deploy.cmd

And a custom boostrapper to install Cake i the kudu environment which could look something like this:

@ECHO OFF
REM SET Cake
SET CAKE_VERSION=0.23.0
SET CAKE_FOLDER=Cake.%CAKE_VERSION%
SET PATH=%~dp0\Tools;%PATH%

REM Cleanup any old Cake versions
FOR /f "delims=" %%c IN ('dir /AD /B "Tools\Cake*"') DO (
        IF NOT "%%c" == "%CAKE_FOLDER%" (RD /S /Q "Tools\%%c")
)

REM Install Dependencies
IF NOT EXIST "Tools" (md "Tools")
IF NOT EXIST "Tools\Addins" (md "Tools\Addins")
IF NOT EXIST "Tools\%CAKE_FOLDER%\Cake.exe" (
    echo Downloading Cake %CAKE_VERSION%
    nuget install Cake -Version %CAKE_VERSION% -OutputDirectory "Tools" -Source https://api.nuget.org/v3/index.json
    )

REM Execute deploy
Tools\%CAKE_FOLDER%\Cake.exe -version
Tools\%CAKE_FOLDER%\Cake.exe build.cake --Target="Publish"

Which basically just cleans up any old Cake versions and fetches 0.23.0 if not already installed.

The complete Cake script would look something like below

#tool nuget:?package=KuduSync.NET&version=1.3.1
#addin nuget:?package=Cake.Kudu&version=0.6.0
    string          target      = Argument("target", "Build");
    FilePath        ngPath      = Context.Tools.Resolve("ng.cmd");
    FilePath        npmPath     = Context.Tools.Resolve("npm.cmd");
    DirectoryPath   outputPath  = MakeAbsolute(Directory("./output"));

    Action<FilePath, ProcessArgumentBuilder> Cmd => (path, args) => {
        var result = StartProcess(
            path,
            new ProcessSettings {
                Arguments = args
            });

        if(0 != result)
        {
            throw new Exception($"Failed to execute tool {path.GetFilename()} ({result})");
        }
    };

    Task("Install-AngularCLI")
        .Does(() => {
        if (ngPath != null && FileExists(ngPath))
        {
            Information("Found Angular CLI at {0}.", ngPath);
            return;
        }

        DirectoryPath ngDirectoryPath = MakeAbsolute(Directory("./Tools/ng"));

        EnsureDirectoryExists(ngDirectoryPath);

        Cmd(npmPath,
            new ProcessArgumentBuilder()
                    .Append("install")
                    .Append("--prefix")
                    .AppendQuoted(ngDirectoryPath.FullPath)
                    .Append("@angular/cli")
        );
        ngPath = Context.Tools.Resolve("ng.cmd");
    });

    Task("Clean")
        .Does( ()=> {
            CleanDirectory(outputPath);
    });

    Task("Install")
        .IsDependentOn("Clean")
        .Does( ()=> {
        Cmd(npmPath,
            new ProcessArgumentBuilder()
                .Append("install")
        );
    });

    Task("Build")
        .IsDependentOn("Install-AngularCLI")
        .IsDependentOn("Install")
        .Does( ()=> {
        Cmd(ngPath,
            new ProcessArgumentBuilder()
                .Append("build")
                .Append("--output-path")
                .AppendQuoted(outputPath.FullPath)
        );
    });

Task("Publish")
    .IsDependentOn("Build")
    .Does( ()=> {
    Kudu.Sync(outputPath);
});

RunTarget(target);

And output on the Kudu build running on your Azure web site would look something like this

             +##   #;;'
             #;;#  .+;;;;+,
             '+;;#;,+';;;;;'#.
             ++'''';;;;;;;;;;# ;#;
            ##';;;;++'+#;;;;;'.   `#:
         ;#   '+'';;;;;;;;;'#`       #.
      `#,        .'++;;;;;':..........#
    '+      `.........';;;;':.........#
   #..................+;;;;;':........#
   #..................#';;;;;'+''''''.#
   #.......,:;''''''''##';;;;;'+'''''#,
   #''''''''''''''''''###';;;;;;+''''#
   #''''''''''''''''''####';;;;;;#'''#
   #''''''''''''''''''#####';;;;;;#''#
   #''''''''''''''''''######';;;;;;#'#
   #''''''''''''''''''#######';;;;;;##
   #''''''''''''''''''########';;;;;;#
   #''''''''''''++####+;#######';;;;;;#
   #+####':,`             ,#####';;;;;;'
                              +##'''''+.
   ___      _          ___       _ _     _
  / __\__ _| | _____  / __\_   _(_) | __| |
 / /  / _` | |/ / _ \/__\// | | | | |/ _` |
/ /___ (_| |   <  __/ \/  \ |_| | | | (_| |
\____/\__,_|_|\_\___\_____/\__,_|_|_|\__,_|

                             Version 0.23.0+Branch.main.Sha.67afe72f1c21a8a3cfd96d3969fb2591d62f37ff


========================================
Install-AngularCLI
========================================
Found Angular CLI at D:/home/site/repository/tools/ng/ng.cmd.

========================================
Clean
========================================

========================================
Install
========================================
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"ia32"})
npm WARN [email protected] requires a peer of @angular/compiler@^2.3.1 || >=4.0.0-beta <5.0.0 but none was installed.
npm WARN [email protected] requires a peer of @angular/core@^2.3.1 || >=4.0.0-beta <5.0.0 but none was installed.

========================================
Build
========================================
Date: 2017-11-17T10:36:45.847Z
Hash: 3b11c732f8aa65f3a08c
Time: 8815ms
chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]
chunk {main} main.bundle.js, main.bundle.js.map (main) 7.79 kB [initial] [rendered]
chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 200 kB [initial] [rendered]
chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 11.3 kB [initial] [rendered]
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.29 MB [initial] [rendered]

========================================
Publish
========================================
KuduSync.NET from: 'D:\home\site\repository\output' to: 'D:\home\site\wwwroot'
Copying file: 'favicon.ico'
Copying file: 'index.html'
Copying file: 'inline.bundle.js'
Copying file: 'inline.bundle.js.map'
Copying file: 'main.bundle.js'
Copying file: 'main.bundle.js.map'
Copying file: 'polyfills.bundle.js'
Copying file: 'polyfills.bundle.js.map'
Copying file: 'styles.bundle.js'
Copying file: 'styles.bundle.js.map'
Copying file: 'vendor.bundle.js'
Copying file: 'vendor.bundle.js.map'
Time 444

Task                          Duration            
--------------------------------------------------
Install-AngularCLI            00:00:00.0491433    
Clean                         00:00:00.0782836    
Install                       00:00:35.4828120    
Build                         00:01:12.5709830    
Publish                       00:00:00.8032134    
--------------------------------------------------
Total:                        00:01:48.9844353    

In the last comment you write that you want to deploy using Octopus deploy, that would basically mean adding 2 new tasks to just like the kudu publish execute post build.

  1. Package up the artifact
  2. Push to Octopus server

For this Cake has the OctoPack and OctoPush aliases.

These aliases require the octo.exe tool, which can be fetch using the tool directive like this

#tool nuget:?package=OctopusTools&version=4.25.0

A pack task could look something like this

    DirectoryPath   nugetPath= MakeAbsolute(Directory("./nuget"));
Task("Pack")
    .IsDependentOn("Build")
    .Does( ()=> {
    OctoPack(
        "PoCApp",
        new OctopusPackSettings {
            BasePath = outputPath,
            OutFolder = nugetPath,
            Format = OctopusPackFormat.Zip
        }
    );
});

Once you packaged your app and pushed package to our octopus server, then you can use their built-in deploy to Azure web app functionality, there's a good guide for that at https://octopus.com/docs/deploying-applications/deploying-to-azure/deploying-a-package-to-an-azure-web-app

Some of the above code is available in the below repo https://github.com/azurevoodoo/NGAppDeployedWithKuduPoC

Donalddonaldson answered 17/11, 2017 at 10:39 Comment(15)
What will be the build.ps1 and build.cake in my case. I am not able to get it properlyAcheron
build.ps1 can be the default recomended described here: cakebuild.net/docs/tutorials/setting-up-a-new-project build.cake is the "complete Cake script" described above. The script above assumes you have ng cli installed globally already.Donalddonaldson
What if on the remote machine where the script will run don't have the npm installed?Acheron
Then either add 'npm install -g @angular/cli' to deploy.cmd/build.ps1 or use Cake.NPM addin to do it as part of your Cake script github.com/cake-contrib/Cake.NPMDonalddonaldson
I'll update the example bootstrapper to install NG cli and provide a link to a example repository later today. Hope that'll make it more clear.Donalddonaldson
Sure thanks. In my case I’ll tell you what we are doing is by using cake we create nuget package and store on build server and later on we deploy to azure using octopusAcheron
Added link to example repo, and install cli step and information about how to pack, which alias to push and where to read more about deploying to azure from Octopus.Donalddonaldson
I am getting failed to install error when i add #tool nuget:?package=OctopusTools&version=4.25.0 line for octopackAcheron
Could be a source thing (if you have others than default configured locally), you can test that by adding source to the tool directive like #tool nuget:nuget.org/api/v2?package=OctopusTools&version=4.25.0 Read more at: cakebuild.net/docs/fundamentals/preprocessor-directives You can also launchCake with diagnostic verbosity to get more detailed errors, read more about that at: #38659160 Could also be old nuget.exe you've got installed, get latest from: nuget.org/downloadsDonalddonaldson
How to pack the contents of output folder into nuget package?Acheron
If you look at the "Install-AngularCLI" you'll see ngDirectoryPath which is the specified path Angular CLI is installed.Donalddonaldson
I wanted the node_modules folder to be located at some other placeAcheron
Adapt the "Install" task above to fit your specific needs by i.e. passing "prefix" parameter in similar way as the "Install-AngularCLI" task. You'll find npm folder documentation at docs.npmjs.com/files/foldersDonalddonaldson
Let us continue this discussion in chat.Acheron
I'm sorry currently don't have time to chat, if you have any specific questions please raise a new Stackoverflow question and I'm sure me or someone else will get to it.Donalddonaldson

© 2022 - 2024 — McMap. All rights reserved.