Automate publish of Angular library as npm package with Azure DevOps

Reading time: 10 minutes

Description

In this post I will explain how to set up continuous deployment of Angular library as npm package with Azure DevOps.

This post will also contain instructions of how to configure the build pipeline, how to configure your Angular application as developer and as a consumer of this package.

I will build two Angular applications for this purpose, so it will be clear to distinguish between the library and consumer applications.

What is required

What’s good about it?

If you are using npm packages you need to host them somewhere. There are several options available. Normally if it’s for public use then it’s free if private or corporate then it obviously costs money. That is their business model.

If you already have an Azure subscription then you have an option to store and host them there. This might be more cost effective but it depends on your needs and availability.

For me it was handy to have an Azure DevOps repo that would have continuous integration trigger enabled, so when I commit a change it would build it and publish it for me.

Once I set up the build pipeline it would do the main stuff related to publishing for me. So the only thing that I would have left to do is set the correct version from my local machine.

Let’s start with initiating a repository for an Angular library on Azure DevOps

Prerequisite: you need a project on Azure DevOps. Go to your Azure DevOps main page.

Once the project is created select Repos from the left side menu. Clone this repo to your computer by copying the url link and using it with your choice of Git GUI.

If you haven’t configured your environment with Angular yet then please do so.

Install Visual Studio Code on your machine. Please use the link below.

https://code.visualstudio.com/download

Then you need to install an appropriate Node.js version that is compatible with your version of Angular.

https://nodejs.org/en/download/

Let’s create an Angular library

Open VS code and navigate to the root folder of the destination where you cloned your repo.

In VS code new terminal type ‘cd destination-of-your-repo’ for example ‘cd C:\Users\dmitr\source\frontend\AzureArtifactsNpmPublish’

Then type

ng new AzureArtifactsNpmPublish --directory=./ --skip-install --create-application=false

The name of this app should match the folder name. This way it will use the root folder and won’t nest it within an extra folder.

As a result you get minimum files created plus it is created straight away in the repo root folder. Pretty neat.

Open the project code files in new the window by typing ‘code .

Then type ‘ng g library your-library-name’ for example ng g library azure-npm-ng-lib

Once you have done this and you are happy with the output please commit-push to Azure DevOps repo.

Before we head on to create a pipeline we need to create the feed that we will be using to store and manage our packages

Select Artifacts from the left side menu of the project on Azure DevOps. Click on Create feed and type in the name for your feed. For Visibility it should be Members of name-of-your-organisation. Make sure Upstream sources Include packages from common publish sources is ticked. As for the Scope select Organization.

All of these settings are applicable to our current needs. If you want to limit who can use the feed then you need to select the appropriate Visibility and Scope.

We are ready to create a build pipeline

Go to the Pipelines section and click Create Pipeline. Then select Classic Editor.

Since we created our repo with Azure DevOps we need to select Azure Repos Git. As for the template, Empty Job will fit our needs.

Because we will use Angular Cli we need Node.js. So the first task will be Node.js Installer.

We also need angular cli install, npm install, npm build and npm publish tasks.

For angular cli install task we need to set Command as custom, in Command and arguments enter ‘install @angular/cli -g’

For the npm install task we will leave it as it is.

For the npm build task we need to set for ‘Working folder that contains package.json’ the location of the root of the library folder within the angular project e.g. ‘projects/azure-npm-ng-lib’
Also in here for ‘Command and arguments’ we need to type ‘run build your-library-name –prod’ e.g. run build azure-npm-ng-lib –prod

For npm publish task we need set ‘Working folder that contains package.json’ with the destination after the application was built. We know that build files are placed by default into the ‘dist/project-name’ folder (you can change this outputPath in angular.json). Hence the location of this library would be at ‘dist/azure-npm-ng-lib’ and the full path ‘$(System.DefaultWorkingDirectory)/dist/azure-npm-ng-lib’
As for ‘Registry Location’ we want to set ‘Registry’ and for ‘Target registry’ we need to pick a registry that is preferably organization scoped.

Additionally we need to set CI trigger and Agent Specification for this pipeline.

Different agent specifications would have different build processes and different paths. For our purpose we will use ubuntu-18.04 agent specification.

Click on the Pipeline section and set the appropriate agent specification for your needs.

Select dropdown of Save & Queue and select Save.

Before we can run it we need to allow this pipeline to make changes to Artifacts feed-registry that we selected in the npm publish task as Target registry.

Once this is done you need to go back to Pipelines and click Run Pipeline. Check the images for more info.

Click on the dropdown of Save & Queue.

If the build is successfull we can find our package under Artifacts side menu option.

*make sure tsconfig.lib.json library level enableIvy is set to false i.e. “angularCompilerOptions”: { “enableIvy”: false }
*and package.json contains scripts part with ng build i.e. “scripts”: { “ng”: “ng”, “build”: “ng build” }

Next we need to configure our machine to use artifacts feed-registry for our npm package

Since we will be storing our npm packages in Azure DevOps feed we need to configure our client machine to use this feed.

There is a helpful section of how to do this under Artifacts. Click on Connect feed and then select npm. On the newly opened section click ‘Get the tools’. This should open a slide menu with description of how to do it.

Since we already configured Node.js and npm at the beginning we can skip to Step 2. Copy the command ‘npm install -g vsts-npm-auth –registry https://registry.npmjs.com –always-auth false’

Open a new terminal in VS code and run it. As an extra check if it was installed you can run this command ‘npm list -g –depth 0’ and see if it’s in the list.

There are more details as to how to set up authentication.

Let’s create another Angular app that would consume our npm package

Before that we need to initiate a repository at Azure DevOps. Select Repos in left side menu. Click a dropdown next to the name of your current repository. Select New Repository.

Clone it to your machine and keep in mind the location.

Open VS code and navigate to that location. Run this command

ng new AzureArtifactsNpmConsumer --directory=./ --skip-install

Make sure the name matches the name of the root folder. This way your app won’t be nested within an extra folder.

Next we need to set up our Angular project according to the provided instructions at Azure DevOps Connect to feed section

Add npmrc file to your root project. In my case this would be ‘C:\Users\dmitr\source\frontend\AzureArtifactsNpmConsumer\.npmrc’

Paste in the first command from Connect to feed description into project level npmrc file.

If you open a user level npmrc file which is located at ‘C:\Users\yourName\.npmrc’ and either take a screenshot or copy it somewhere as a backup before it is be modified.

Then run this command in the same project ‘vsts-npm-auth -config .npmrc’.
You will be prompted with a login window. Follow the onscreen instructions to complete the authentication process.

Now if you close and open again the user level npmrc file you would be able to see the difference.

There’s another thing you can do to assist the process of the authentication. Open package.json of the project you are working on and add this bit “refreshVSToken” : “vsts-npm-auth -config .npmrc” into the scripts section. So it would look like so “scripts”: {“refreshVSToken” : “vsts-npm-auth -config .npmrc”}

So in case you are required to refresh the token you can write in terminal ‘npm run refreshVSToken’ and it should reauthenticate you/refresh the token at user level npmrc file.

Basically what is happening behind the scene is every time we run npm install the authentication process kicks in. The token that is in the npmrc file at user lever location is exchanged with registry-feed, so that user machine gets authenticated.

Let’s test if we can install our library package to our Angular consumer app

Please go to the Artifacts at Azure DevOps from there into the package details page and copy the full command to install the package. For example ‘npm install azure-npm-ng-lib@0.0.1’

Use this command in the Angular app where you want to access this npm package.

Next let’s add some code to Angular app and test if we can use npm package code

Open app.component.ts and add this code.

constructor(private _azureNpmNgLibService: AzureNpmNgLibService) {
  }

  ngOnInit(): void {
    this.mainFunc();
  }

  mainFunc(){
    let message = this._azureNpmNgLibService.getMessage();
    console.log(message);
    console.log(123)
  }

So it would look like the image below. Then run ‘ng serve -o’ and open the developer tools. Check if the console/debugger tab contains our ng library npm package message.

Next let’s apply a change and increase the version of lib package

In terminal navigate into folder where library files live and type in ‘npm version 0.0.2’ e.g. C:\Users\dmitr\source\frontend\AzureArtifactsNpmPublish\projects\azure-npm-ng-lib> npm version 0.0.2
This way the package.json version of the library would be updated.

Optionally change the message.

export class AzureNpmNgLibService {

  constructor() { }
  
  getMessage(){
    return "wow what an update! is it the font or a colour :-D"
  }
}

Then commit-push these changes. This should trigger a new build.

This should update our existing package to 0.0.2. You can check this at the Artifacts section.

Next let’s update our Angular consumer app to the latest version of our npm package

In the terminal type in ‘npm outdated’. This would list all the packages that have updated versions.

To update the package to the latest version we need to use ‘npm i azure-npm-ng-lib@latest’ You can also target a particular the version then you need to write what version number like so ‘npm i azure-npm-ng-lib@2.0.0’

Once it is updated to the latest version it is removed from the outdated list. If it’s not the latest it will still be there. For instance if you have 3 versions and your app uses version number two.

Npm follows semantic versioning, more details here.

Conclusion

As you have noticed there are a lot of tips available on Azure DevOps that can guide you through the whole process. As long as you are aware of the process of how npm packages are published to the npm registry all of this should make sense.

If you want an original guide from Microsoft you can find it here.

In my opinion this combination of npm packages and build pipeline with Azure DevOps can be extremely helpful.

It’s one of those things you set up once and you can enjoy the effectiveness of it from then on. In essence you have moved the main heavy lifting(building and publishing) to a cloud based server, so it’s doing it for you.

Moreover you can see the history and related description of changes in a more familiar format.

You can find code for ng library package here and consumer app here.

Azure Service Bus Queue with MassTransit


Reading time: 13 minutes

Description

In this post I will explain how to create a bus queue and consume it. The case study would be around the order system. Let’s imagine a system where you can create a new order for whatever reason in the industry you like. This could be an e-commerce website, an airplane or bus ticket ordering website.

What is required

  • Azure Subscription
  • Visual Studio
  • Net Core Web App

Let’s start by creating a Net Core App

Open Visual Studio and choose ASP.NET Core Web Application. Choose an API project template.

This project is going to be our Sender according to Microsoft resources or Producers according to Masstransit documentation.

In the same solution add New Project and select Class Library (.Net Standard) This project will contain our Contracts. You can read a definition for it here or here.

The reason why we add the class library of Net Standard is because it provides a uniformity in the .Net ecosystem. In other words if you got two projects of different .Net platform versions(.Net Framework 4.5 and .Net Core 3.1) thanks to .Net Standard these would be able to share a particular class library without any issues.

Now we need to add a Consumer or Receiver. In essence this is where our message would end up going. Or you can process it and send it further where you want to.

Add a new web app project to this solution and select Empty template.

Next thing is to add several Nuget packages

We need to install several MassTransit related packages in addition to Azure Service bus.

Required packages:

Right click on the project and select Manage Nuget Packages. In that tab search for each of these packages and install them to Sender and Consumer projects.

Installed Nugets should look like this.

Next thing we would be adding the code to send and consume message

In the Controller folder of the Sender project add a new controller. I will call it OrdersController. Next add the HttpPost method NewOrder.

Action method should look like this.

    [HttpPost()]
        public async Task<IActionResult> NewOrder()
        {
            var sendEndpoint =
             await _sendEndpointProvider.GetSendEndpoint(
                 new Uri("sb://servicebusqueuesnetcore.servicebus.windows.net/new-orders"));

            await sendEndpoint.Send(
                                        new Order
                                        {
                                            OrderId = Guid.NewGuid(),
                                            Timestamp = DateTime.UtcNow,
                                            PublicOrderId = _random.Next(1, 999).ToString()
                                        });

            return Ok();
        }

We also need to add a contract. In the Contracts project add a new class and call it Order. Add all properties that you require. It should look like the example below.

public class Order
    {
        public Guid OrderId { get; set; }
        public string PublicOrderId { get; set; }

        public DateTime Timestamp { get; set; }
    }

Let’s go back to the Sender project and open the Startup file. In it we will add a service bus, MassTransit, register and define endpoints.

In there we need to edit the ConfigureServices method in order to add required services to the DI container.

This is how it should look like.

 public void ConfigureServices(IServiceCollection services)
        {
            var connectionString =
        "Endpoint=sb://servicebusqueuesnetcore.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=blablasharedaccesskey";

            var newOrdersQueue = "new-orders";

            // create the bus using Azure Service bus
            var azureServiceBus = Bus.Factory.CreateUsingAzureServiceBus(busFactoryConfig =>
            {
                busFactoryConfig.Host(connectionString);

                // specify the message of Order object to be sent to a specific queue
                busFactoryConfig.Message<Order>(configTopology =>
                {
                    configTopology.SetEntityName(newOrdersQueue);
                });
            });

            services.AddMassTransit
                (
                    config =>
                    {
                        config.AddBus(provider => azureServiceBus);
                    }
                );

            services.AddSingleton<ISendEndpointProvider>(azureServiceBus);
            services.AddSingleton<IBus>(azureServiceBus);

            services.AddControllers();
        }

Next we need to perform a similar sort of changes in the Consumer project.

Add a new class and call it OrderConsumer. Inside let’s add some code.

  public class OrderConsumer 
        : IConsumer<Order>
    {
        public Task Consume(ConsumeContext<Order> context)
        {
            System.Threading.Thread.Sleep(60000);//Wait for one minute

            //by returning a completed task service bus removes message from the queue
            return Task.CompletedTask;
        }
    }

Next let’s add HostedService that would start and stop our service bus. It’s very important to start service bus before attempting anything.

Add a new class and call it BusHostedService.

public class BusHostedService
        : IHostedService
    {
        readonly IBusControl _busControl;

        public BusHostedService(
            IBusControl busControl)
        {
            _busControl = busControl;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            await _busControl.StartAsync(cancellationToken);
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await _busControl.StopAsync(cancellationToken);
        }
    }

Next it’s Startup files turn. Similar changes as for Sender Startup. We need to configure services that would be available through Dependency Injection.

Note: Queue name should match between Sender and Consumer.

 public void ConfigureServices(IServiceCollection services)
        {
            var connectionString = "endpoint of your service bus";
            var newOrdersQueue = "new-orders"; // need to make sure the queue name is written correctly

            services.AddMassTransit(serviceCollectionConfigurator =>
            {
                serviceCollectionConfigurator.AddConsumer<OrderConsumer>();

                //Consumers - Receivers
                //Message Creators - Senders
                //would normally be in different applications

                serviceCollectionConfigurator.AddBus
                    (registrationContext => Bus.Factory.CreateUsingAzureServiceBus
                                                    (configurator =>
                                                    {
                                                        configurator.Host(connectionString);

                                                        /*
                                                         For a consumer to receive messages, the consumer must be connected to a receive endpoint. 
                                                        This is done during bus configuration, particularly within the configuration of a receive endpoint.
                                                        https://masstransit-project.com/usage/consumers.html#consumer*/

                                                        configurator.ReceiveEndpoint(newOrdersQueue, endpointConfigurator =>
                                                        {
                                                            endpointConfigurator.ConfigureConsumer<OrderConsumer>(registrationContext);
                                                        });
                                                    }
                                                    )
                     );

            });

            //need to always start the bus, so it behaves correctly
            services.AddSingleton<IHostedService, BusHostedService>();
        }

Next thing we need to create Azure Service Bus

For this we need to go to Azure Portal home. Select Create a Resource.

On the next screen choose Integration then in the right pane menu Service Bus.

When you are creating Service Bus the things to consider are Resource group, Location and Pricing tier.

For Resource groups either create a new or select the existing one. If it’s part of existing then you can manage it with other resources in that group.

Normally Location should be local to you as different regions/locations have different regulations, latency etc. You can either use the same region or pair them. For example your web app uses UK South, so you would consider using UK South instead of East US for your service bus. If you are pairing then consider using UK South and UK West.

However there are no limits as to what region and location to use. As long as it answers your personal or business requirements. You can read more about regions here and here.

If you consider using different regions then check out this Microsoft article.

As for the tier let’s use the Standard pricing tier since it always works and it’s easier to set up.

Note: Azure charges money for this tier. So make sure you use it accordingly and delete the service bus once you stop playing with it.

Once it’s successfully deployed we need to go and retrieve the connection string for our application. Go to the resource and select the service bus namespace.

On your service bus find Settings and select Shared access policies. Then select RootManageSharedAccessKe and copy Primary Connection String.

We need to paste the whole string into the connectionString variable value in the Startup file of Sender and Consumer projects.

Next let’s test what we created

Since we have Sender and Consumer in the same solution we need to set this solution to run multiple projects. Right click on the solution, select radio button for Multiple startup projects. From the dropdown of Action columns select which projects to run.

To simplify things disable SSL for Sender and Consumer projects. On the Sender project right click and select Properties. In the newly opened tab select Debug and find Enable SSL checkbox. Untick it and save it.

Run the solution.

Because we need to hit HttpPost method we would require some sort of API client tool. For this example let’s try out Postman.

Let’s grab the URL of our Sender project and put it into the Postman tab with HttpPost method type selected. We also need to prefix it with controller route.

http://localhost:58852/api/orders

It should return Status 200 OK if everything went ok.

Next let’s check our Azure Service Bus on Azure portal

If you go back to azure portal and open our service bus namespace. Every time you hit the HttpPost method a message will be enqueued. The consumer will process it when it will become available. One of the message models of Azure Service Bus Queues is First in, First out(FIFO).

As you can see our Queue has been added. If you click on it you would be able to see some stats and message count.

Because we suspend current thread for a minute the Consumer will process each new message once this time has passed. So if you hit that HttpPost method several times all these messages will be added to our queue one by one. However the message will start to process after one minute from the moment it was added.

public Task Consume(ConsumeContext<Order> context)
        {
            System.Threading.Thread.Sleep(60000);//Wait for one minute

            //by returning a completed task service bus removes message from the queue
            return Task.CompletedTask;
        }

By returning a completed task this message will be removed from the queue.

Before we wrap up we need to tidy things up

This is especially the case because we are using the Standard pricing tier for this Service Bus namespace.

There are several options as to how to do it.

You can delete the Service Bus namespace on the page itself.

Another option is to delete a Resource group altogether.

Conclusion

Azure Service Bus is a cloud messaging service. What is appealing is the simplicity of use and set up. What makes it even more easier is the addition of MassTransit, a distributed application framework which is responsible for abstracting the transportation.

By using these tools correctly you are able to achieve service decoupling with no sweat. There are other reasons to use it. To name a few, the application scaling, asynchronous processing and monitoring.

Source code

Continuous Deployment of Net Core Web App to Azure App Service

Reading time: 15 minutes

Description

In this post I will explain how to setup continuous deployment of Net Core Web App with Azure DevOps for the app that is hosted with Azure App Service.

What is required

  • Azure Subscription
  • Net Core Web App
  • Repository/Repo on Azure DevOps

Let’s start with initiating a repository on Azure DevOps

Prerequisite: you need a project on Azure DevOps. Go to your Azure DevOps main page.

Once you have clicked Create you should see similar screen.

We are interested in Repos section.

Look at the top section of the page where it says Initialize with README or gitignore. In my opinion it is a good practice to have both of these files with every repository you are creating.

With README you are deemed at some point to add some description of your app. This serves as an initial documentation. Whereas gitignore will prevent you from commiting unnecessary files to your repository. In a production environment this save your builds and time in case one or few files has slipped through.

At the end of the day you can always delete them or edit them according to your requirements.

Clone repository

Next thing is to Clone this newly created repository to your machine.

You can use any GUI for Git to do it or even Git Bash if you prefer command line type of application.

For this case I will use Sourcetree . It’s relatively easy to use. Gitextensions is similar in touch and feel. It also nicely connects with various comparison/diff and merge tools.

The main thing for us is to memorize the destination where we clone our reposity.

Create Net Core App

Let’s create Net Core web app with Visual Studio.

Since we already created a solution folder when we cloned the repository to our machine make sure in Location field we target the folder that contains the solution folder named NetCoreWebApp. Visual studio clever enough to place web app files into this folder.

Then we select ASP .Net Core 3.1 with Angular template.

The final folder structure should looke like so.

NetCoreWebApp inside has this structure.

Alternatively you can always create web application at one destination and then simply copy or move it over to the repository location.

In either way the result that we aiming for is for Git to track the changes to the repository.

As you can see Sourcetree on top of Git picked up the changes to your repository.

Steps that you need to do next are:

  • Good practice is to Build the solution but in this case it can be optional since it’s a pre-made template
  • Stage All
  • Write commit message
  • Commit
  • Push it to the remote server.

Once all of these steps are performed you would be able to see your changes on your repository at Azure DevOps.

Build pipeline

Select Pipelines from left menu and Use the classic editor.

Then select the repository you wish to setup the build pipeline.

Then you need to choose ASP.NET Core template.

The next screen should look like this.

The only thing that needs changing is on the Triggers tab.

This way we enable Continuous integration. Which means every time you commit changes to this branch it would trigger the build pipeline. As a result you would be able to see whether your changes integrate into the code of remote copy of the branch. In our case it’s master. Normally you would have build pipeline on develop branch before merging and building it on master branch.

Next step is to click on Save & queue. Then we need to add comment, check the branch and click Save and Run.

Next screen should look like this.

Next we need to create an App Service

For this we need to go to Azure Portal.

There we need to select Create Resource.

Then select Web and Web App.

Things to fill in on the next screen:

  • Resource Group -> Create new, choose whatever name you like since by it you will distonguish resource group that is related to particular project.
  • Name – which would be part of web app url
  • Way of publish – Code
  • Runtime stack that your app would use to run
  • Operating system – Windows
  • Region – whatever you like. Mind since we are using free subscription you need to make sure it is available in that region.
  • Windows Plan -> Create new
  • Free F1 tier which is part of free subscription from Azure for individual developers that want to research this platform

If you go to your newly created resource and there select App Service. From there you can check the app if it’s ok and running fine by clicking on it’s url.


Let’s go back to Azure DevOps and create Release pipeline.

…before getting into final part I think it’s a good time for a cup of beverage of your choice 😉

Create Release pipeline

Click on Releases from left pane menu. Then click on New pipeline in the area on the right.

Search for Azure app in the search box for templates. Click Apply.

From there you can edit stage details like name and owner. This could be develop stage with one of the testers being the owner. However in our case we will leave these as they are.

We are more interested in editing job/task section. So let’s click on section that is underneath Stage 1 in Stages on the left side.

In here we need to select our Subscription and App service name that we created at Azure portal.

Once we selected and Authorized our subscription we can then see our available App services.

Let’s go back to tab Pipeline and add an Artifact that was created by the build pipeline. Click on Add an artifact.

Select appropriate build pipeline Source. Check alias and edit it if needed. Click Add.

Last bit of setup. The Continuous deployment trigger.

Save and click Create release.

Select the Stage and build version that you want to release.

Once you are happy click Create.

Go to Releases on the left pane. In the right section click on Releases.

You would need to deploy the first release manually. On the next screen click Deploy and off it goes!

You can monitor the process in the next screen.

To check your newly released web app select Deploy Azure App Service.

For this purpose use App Service Application url.

Let’s check out the result! Our Hello, world app! Classic 🙂

Conclusion

Hope you enjoyed this post.

As you have noticed with Azure it is quite straight forward to deploy an app. From creating an App service in portal to creating build pipeline with Azure DevOps. When you have done it once or twice it makes sense. You can easily connect the dots to get the whole picture of modern deployment processes.

Stay tuned and have fun coding.

Continuous Deployment of Angular SPA to Azure App Service

Reading time: 15 minutes

Description

In this post I will explain how to setup continuous deployment with Azure DevOps. This post will also contain instructions of how to host it using Azure App Service.

What is required

  • Azure Subscription
  • Angular App
  • Repository/Repo at AzureDevOps

What is continuous deployment?

Continuous deployment is the final stage of CI/CD development approach. It is responsible for deploying code to different environments. For example, develop, staging and production. Deployment happens automatically in comparison to Continuous Delivery. With continuous delivery the only difference is that the release to production happens manually. It involves someone from the engineering team or someone from product team or even management to click a button.

In a nutshell CI/CD is a practice that is followed by an engineer or a group of engineers that work on a common code of any application that is under constant development and which requires to be build, tested and released as soon as the code is being pushed to a git a branch that is responsible for kicking this process off. Normally it is a develop branch.

Main benefit of CI/CD approach is that the code is in deployable state at all times. Of course, this is in theory but in practice this could be more or less true because in order for this approach to be effective team have to be disciplined and implement whatever is required for it. There are a lot of resources online for different situations. This would all depend on the current team approach, requirements and objectives.


Let’s roll up our sleeves and get stuff done

Setup local environment and workspace for Angular app

Install Visual Studio Code on your machine. Please use the below link.

https://code.visualstudio.com/download

Then you need to install appropriate Node.js version that is compatible with your version of Angular.

https://nodejs.org/en/download/

Create Angular app

It is a straight forward task once your local environment and workspace is set up.

  • Open VS code
  • Go to Terminal > New Terminal
  • Install the latest Angular version globally with this command > npm install -g @angular/cli
  • type in > ng new my-app
  • use this command to go to code > cd my-app
  • make sure it works fine by opening the app using this command > ng serve -o

Create repository on Azure DevOps

Prerequisite: you need a project on Azure DevOps. Go to your Azure DevOps main page. The url should look similar to the below one.

https://dev.azure.com/your-username-for-azure-account/

Next thing is to initialize a repository. Select Repos from left panel. If you don’t have any repos in there then you should see similar page.

You need to initialize a repo for it be able to clone to your machine. Once it is cloned you need to copy files your previously created angular app into location where you have cloned the repo to. This way source control app on top of Git will detect changes. By the way you need Git installed on your machine.

*In case you got other repos on the project you can simply add another one like so.

Make sure you give a descriptive repository name. If you want to avoid complications then it should be without spaces. Also select at least README. Alternatively, you can add .gitignore. You can always delete them or replace them. This way your repository won’t be empty and you can check it out with no issues.

Create Azure App Service

Select App Services at Azure portal home screen.

On next screen select Add.

Then select suitable subscription that is available on your account. For this task Free Trial subscription would be sufficient.

Next create New Resource Group.

Resource group serves as a container for related projects of your application that you host on Azure. More information at Microsoft documentation following this link https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal

Next fill in Instance details section.

Name is App name plus it constructs part of the URL.

In our case the app code will be published, so let’s leave Code as selected option.

Runtime stack relates to this particular instance of app running on an Azure server. Whatever you choose it should be applicable to your application. In other words, your app should be able to run on this stack. Different runtime stack would behave differently, would have different DLLs running and so on.

For our case we need to run Angular app on .NET V4.7 because angular app needs a server to run the app. This will provide us with an option to run the app on IIS which comes with the framework. Alternatively, you can choose .NET Core. This might need some tweaking but in theory it has IIS server too, so should run with no issues. More information https://docs.microsoft.com/en-us/aspnet/core/fundamentals/choose-aspnet-framework?view=aspnetcore-3.1 and here https://angular.io/guide/deployment#server-configuration

As for operating system select Windows.

Depending on the Region you can have different App service plans. For example, since we are using Free Subscription not all regions will have a Free F1 plan and sometimes you need to pick the right one for your needs.

Finally, it should look similar to below image.

Confirm your app settings by clicking Review + create. All done!

Let’s go back to AzureDevops to implement continuous deployment

Create build pipeline

Select Pipelines from the left menu and then click on ‘Use the classic editor’ in the section on the right.

Next select our previously created repository and click Continue.

For our purpose we need an Empty Job where we can customize all the steps and processes for this build pipeline. Other options are premade templates that can speed up pipeline setup.

Next screen should give you different options to structure this pipeline. What we need is to add a task to an Agent Job.

First task would be the Node.js tool installer. You would need to choose an appropriate version to run with your angular app. For example, I will pick version 12.x for Angular 9 app.

Then we need to follow the same pattern and add a npm task.

We need to replace default field content with custom values. In our case we are making sure the pipeline has latest angular installed.

Then we need add another npm task where we explicitly say to install all the packages and dependencies for our Angular app. Here we leave a default field content.

Now we need to add a production build task. Again, we will use npm task.

When app is build using ‘build –prod’ command it creates ‘dist’ folder with app name folder inside. In this folder you got app build files that would be used on the server to run your app.

As you can see on the image below inside we got a folder with app name containing transpiled and minified JS files plus other files required for app to run.

Next step is to archive files into particular location on the server. Let’s search pre-set tasks for an archive task.

Change root folder to System.DefaultWorkingDirectory. It is the place where your source code files are downloaded. More details https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml

And also untick ‘Prepend root folder name to archive paths’.

Last task to add will be to publish build artifacts.

There is nothing that we need to change.

So, the final set of tasks for build pipeline should look like this.

To make it so that every time there is a change to the branch it would trigger a new build we need to select ‘Enable continuous integration’ flag in Triggers section. By doing so we are achieving continuous integration of code.

This looks like it. Now we need to click Save & queue, add save comment and click Save and run.

This will start the build pipeline. During the build all the tasks that we established would be done sequentially.

Create release pipeline

Select Releases under Pipelines in the left side navigation menu.

If you do not have any pipelines you can add a new pipeline by clicking on New Pipeline.

In case you have existing pipelines, you can add new release pipeline by using dropdown as you can see on the image below.

Next thing to add is Azure App Service deployment task.

After that you need to click Tasks tab and select your subscription with app service for this web application.

Once this is done we need to go back to Pipeline tab and select our artifact that we published in the build pipeline.

We keep everything as it is after we choose Source build.

To enable continuous deployment, we need to activate the continuous deployment trigger. Once you have added a build artifact you can click on continuous deployment trigger icon. In the side pop out window you need to set toggle to Enabled.

Additionally, if you got a requirement to set this trigger on particular branch e.g. master, develop etc you can easily do so in the same window. This way the release pipeline will listen to a build on particular branch e.g. develop, yourtestbranch etc

Click Save, then Create release.

Go to Releases on the left pane. In the right section click on your Release created in the previous step.

You would need to deploy the first release manually. Click Deploy

That is it.

Oh, wait one more thing. Go back to Azure portal and find our previously created App Service. Select Configuration from Settings in the left side menu option. Move to the right side and select Path mappings tab. On that tab edit Physical Path under Virtual applications and directories, so that it reads site\wwwroot\dist\ng-app\

This will make sure you are able to access your web application.

Conclusion

This tutorial shows you how to setup CI/CD using Azure portal and Azure DevOps. These two work hand in hand. Since it is all under one Microsoft account it becomes really easy to connect everything together and see results straight away.

CI/CD pipelines serve as handy and straight forward mechanims that can greatly improve the performance of the team. It can also increase the output by automating a lot of processes related to building, testing and deploying of your application.