Publish a package with Visual Studio to Nuget

Description

In this post I will demonstrate how to publish a Net Standard class library as a package to the Nuget server/repository.

I will also touch on versioning, managing and deleting this package.

What is required

*If you have a Microsoft account this should be very easy since Nuget and Visual Studio use the same account.

Let’s get straight into action by creating the net core application

You can either have a Nuget package as a dedicated application for packages or it being a project within an application. For instance if you have a class library containing shared contracts or models within an api application.

We can start by either creating a Blank Solution and then manually adding a class library or choose a Class Library straight away. For the latter the solution is created automatically. However the name of the class library would be the same as the class library itself.

I will do the Blank Solution option and manually add the class library.

Class Library should be of Net Standard, as it provides compatibility with different projects of various Net implementations.

Let’s get our package ready to be published

I think it’s a good time to mention several points in regards to versioning of the nuget packages. A recommended approach is to use SemVer or the full name is Semantic Versioning. It follows the format of Major.Minor.Patch[-Suffix]

  • Major: Breaking changes
  • Minor: New features, but backwards compatible
  • Patch: Backwards compatible bug fixes only
  • -Suffix (optional): a hyphen followed by a string denoting a pre-release version (following the Semantic Versioning or SemVer 1.0 convention).

For example 1.2.3, 1.5.9-prerelease. In general whatever suffix you put the Nuget package manager will put it under prerelease type. This means you would have to tick ‘Include prerelease’ in Visual Studio when searching for nuget packages.

When searching make sure you got the correct source selected. You can check the settings by clicking on cogwheel icon or go to Tools > Options > Nuget Package Manager > Package Sources

Okay if you open properties for the Class Library you created. Right Click >Properties. In there you would be able to see a place where you can set the required version number. It would be under Package option.

Let’s pack it

In the solution explorer of Visual Studio right click on your class library and select Pack.

This should produce a nupkg file in Debug(Release folder on server or in production mode) folder that is inside the bin folder which in its turn is placed in the class library root folder. For example C:\Users\dmitr\source\backend\DgVsNuget\DgLoggers\bin\Debug

This also generates a nuspec file but instead of a bin folder it would be in the obj folder. For example C:\Users\dmitr\source\backend\DgVsNuget\DgLoggers\obj\Debug
This file contains package metadata like id, package version, authors etc. Some details we set when we edited values in class library properties under Package option.

Let’s publish it

Firstly let’s check if we got net core cli installed. For this we need to open Command Prompt and type in ‘dotnet’ command.

Then we need to navigate to the folder where our nupkg file lives. For me it’s C:\Users\dmitr\source\backend\DgVsNuget\DgLoggers\bin\Debug

The complete command should look like this ‘cd C:\Users\dmitr\source\backend\DgVsNuget\DgLoggers\bin\Debug’

Then we need to run the command which would contain the name of your package file, as it is in the bin/Debug or bin/Release folder, the api key that you generate in your account with Nuget and also the source url.

For me the command would look like so ‘dotnet nuget push DgLoggers.1.0.1-prerelease.nupkg –api-key qz2jga8pl3dvn2akksyquwcs9ygggg4exypy3bhxy6w6x6 –source https://api.nuget.org/v3/index.json’

Api key can be generated on your account at nuget.org
For Glob Pattern enter star *

For source we put https://api.nuget.org/v3/index.json because we use Nuget server. The url is the same format with possible version differences.

Once you assembled the command type it into command prompt/net core cli and hit the enter.

Once it successfully pushes you can view it in your Nuget Account. For a brief moment it would be in Unlisted state. Once Nuget approves it will go into Published state.

I would recommend setting it as Unlisted. This way it’s not searchable. You can still install it with the version you need. For this you need to go to your Nuget Account and select Manage Packages. There you would see Published Packages and option to go to package details. Once you are on the manage page for the current package you can deselect the listed option.

Let’s use this package

Since we set this package as Unlisted we need to use the package manager console and use the install command where you specify the version.

Firstly create a new Asp.Net Core Application as web api.

Once the application is created go to Package Manager Console and type in Install-Package Your-package-name -Version the-version-you-need
For example Install-Package DgLoggers -Version 1.0.1-prerelease

Install-Package DgLoggers -Version 1.0.1-prerelease

You can find the complete command at the Nuget page for your package. The url should be of this format https://www.nuget.org/packages/your-package-name/

After that initiate package TextLogger class and call Log method with supplied message in the controller of your choice.

[HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            //here we initiate the package logger
            var pckgLogger = new TextLogger();
            pckgLogger.Log("test logger");

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

When you run the application check the Output window for this message.

Let’s talk about deleting the package

As it’s stated on Microsoft page nuget.org does not support permanent deletion. There are exceptions but not many. And you have to contact the Nuget team.

Despite that you can unlist the package. Which essentially means it’s still active and can be installed but not searchable. So you have to know that such a package exists and know the versions that are available.

Even though Nuget Cli provides a delete method, what it does is it simply unlists the package. The package has to be active/published.

Just to give you an idea of the process. Let’s go back to nuget.org and activate/list our package.

The required details we need are the same as for when you publish the package. For this we need to generate the api key at nuget.org. When generating the api key make sure Unlist package scope is ticked.
We also need to include the source as https://api.nuget.org/v3/index.json into the delete command.

The complete command should look like so dotnet nuget delete DgLoggers.1.0.1-prerelease.nupkg –api-key qz2jga8pl3dvn2akksyquwcs9ygggg4exypy3bhxy6w6x6 –source https://api.nuget.org/v3/index.json

dotnet nuget delete DgLoggers 1.0.1-prerelease --api-key qz2jga8pl3dvn2akksyquwcs9ygggg4exypy3bhxy6w6x6 --source https://api.nuget.org/v3/index.json --non-interactive

Let’s go back to Visual Studio and run it in the Package Manager Console. Alternatively you can use command prompt/net core cli.

So if you go back to your package on nuget.org it should be set as unlisted.

Let’s talk about updating the package too

As you can imagine the process is the same as when we publish the package. We need to change the version in the Project Options Package section. Then pack it. To note we need to use the newly generated nupkg file name. For instance DgLoggers.1.0.2-beta.nupkg

Then run the command in net core cli/command prompt.

dotnet nuget push DgLoggers.1.0.2-beta.nupkg --api-key qz2jga8pl3dvn2akksyquwcs9ygggg4exypy3bhxy6w6x6 --source https://api.nuget.org/v3/index.json

If it’s in status listed at nuget.org then Nuget Package Manager in Visual Studio would pick up that there is a new version available. Simply update it from there.

If it’s not listed then you need to do it manually by using the command from nuget.org for your package with a specific version.

Conclusion

Having nuget packages with the code that would be reused is a great way of preventing code duplication.

Possibly you just want to isolate a particular piece of code from the main source code. That works too.

You can think that the code in the package follows the object-oriented principle of abstraction. As long as we know what the package does and what methods are available to use there is no need to know details of package code.

It still depends what you will put in there, might be simply some contracts or models that you want to share between projects. It’s up to you. Hopefully something reasonably sized.

You can find a code for the package here and the consumer application here.

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.