Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Month: May 2023

Semantically Generating NuGet Package Versions: Best Practices Using Branch Conventions in Azure DevOps Pipelines

Learn how to streamline NuGet package versioning in Azure DevOps pipelines by generating semantic versions based on branch conventions. Proper versioning is essential for effective package management, and semantic versioning ensures compatibility and clear communication of changes.

a few main use cases for this e.g when you want to share schema of common objects or library across different micro services/API but at the same time you would be able to make a minor changes and try it on your micro service before it is being merged to master therefore you want to create a nuget package version that is just for development or testing purpose before it is going to be merged. This is all possible and is managed through versioning convention

A few things to look below are – the variables (Major, Minor, Patch, versionPatch, versionNumber) and you can also look at how we have a task to append “alpha” and you can also change to “beta” to the version variable when the branch is not master. You also need to set the versioningScheme on nuget pack to use the version variable that you defined above versionNumber

For the stable version now you can see in nuget package manager and make sure to untick “Prerelease”

While for the version comes off the branch now you need to tick “include prerelease”

Sample pipelines yml below

trigger:
  batch: true
  branches:
    include:
    - '*'

pool:
  vmImage: ubuntu-latest

variables:  
  projectName: 'Contoso.Messaging.csproj'
  projectPath: '**/Contoso.Messaging.csproj'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  Major: '1'
  Minor: '0'
  Patch: '0'
  versionPatch: $[counter(variables['Patch'], 0)]
  versionNumber: $(Major).$(Minor).$(versionPatch)

steps:

# Add this Command to Include the .NET 6 SDK
- task: UseDotNet@2
  displayName: Use .NET 6.0
  inputs:
    packageType: 'sdk'
    version: '6.0.x'

- task: DotNetCoreCLI@2
  displayName: 'Restore'
  inputs:
    command: 'restore'
    projects: '$(projectPath)'

- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    arguments: '--configuration $(buildConfiguration) -p:Version=$(versionNumber)'
    projects: '$(projectPath)'
    
- script: echo '##vso[task.setvariable variable=versionNumber]$(versionNumber)-alpha'
  displayName: "Set Nuget package version number"
  condition: ne(variables['Build.SourceBranchName'], 'master')

- task: DotNetCoreCLI@2
  displayName: 'Pack'
  inputs:
    command: 'pack'
    packagesToPack: '**/*.csproj'
    versioningScheme: 'byEnvVar'
    versionEnvVar: 'versionNumber'
    outputDir: '$(Build.ArtifactStagingDirectory)'

- task: NuGetAuthenticate@0
  displayName: 'NuGet Authenticate'

- task: NuGetCommand@2
  displayName: 'NuGet push'
  inputs:
    command: push
    nuGetFeedType: 'internal'
    publishVstsFeed: 'xxxxxxxxxxxxxxxxxx'
    allowPackageConflicts: true

Read and remove scheduled message in Azure Service Bus

Ever wondered on how you can remove the scheduled message in Service bus topic or queue? We had a bug where one of our service keep queuing the messages while its not meant to be queued and we deployed the fix but in order to test the fix we need to make sure there are no messages are being scheduled therefore we need to remove all scheduled messages to test if the fix is working

At the same time you can also use the same code to check your messages if it is all being scheduled properly based on your logic

I was expecting the service bus explorer on azure portal allow us to peek into this scheduled messages but unfortunately it doesn’t have this feature

for service bus topic you can use below code

class Program
    {

        // Connection String for the namespace can be obtained from the Azure portal under the
        // 'Shared Access policies' section.
        const string ServiceBusConnectionString = "[Servicebus connection string with entity path]";
        static ITopicClient topicClient;
        static IMessageReceiver messageReceiver;

        static void Main(string[] args)

        {
            MainAsync().GetAwaiter().GetResult();
        }

        static async Task MainAsync()
        {
            var sbConnStringBuilder = new ServiceBusConnectionStringBuilder(ServiceBusConnectionString);
            topicClient = new TopicClient(sbConnStringBuilder);
            Console.WriteLine("======================================================");
            Console.WriteLine("Press any key to exit..");
            Console.WriteLine("======================================================");

            messageReceiver = new MessageReceiver(sbConnStringBuilder);

            Message message = await messageReceiver.PeekAsync();

            // Message with property ScheduledEnqueueTimeUtc not null means it is a scheduled message

            while (message != null)
            {
                if (message != null && message.ScheduledEnqueueTimeUtc != null)
                {
                    // Remove the scheduled message
                    await topicClient.CancelScheduledMessageAsync(message.SystemProperties.SequenceNumber);
                }
                message = await messageReceiver.PeekAsync();
            }

            Console.ReadKey();
            await topicClient.CloseAsync();
        }

    }

For the service bus queue you can use code below

class Program
    {

        // Connection String for the namespace can be obtained from the Azure portal under the
        // 'Shared Access policies' section.
        const string ServiceBusConnectionString = "[Servicebus connection string with entity path]";
        static IQueueClient queueClient;
        static IMessageReceiver messageReceiver;

        static void Main(string[] args)

        {
            MainAsync().GetAwaiter().GetResult();
        }

        static async Task MainAsync()
        {
            var sbConnStringBuilder = new ServiceBusConnectionStringBuilder(ServiceBusConnectionString);
            queueClient = new QueueClient(sbConnStringBuilder);
            Console.WriteLine("======================================================");
            Console.WriteLine("Press any key to exit..");
            Console.WriteLine("======================================================");

            messageReceiver = new MessageReceiver(sbConnStringBuilder);

            Message message = await messageReceiver.PeekAsync();

            // Message with property ScheduledEnqueueTimeUtc not null means it is a scheduled message

            while (message != null)
            {
                if (message != null && message.ScheduledEnqueueTimeUtc != null)
                {
                    // Remove the scheduled message
                    await queueClient.CancelScheduledMessageAsync(message.SystemProperties.SequenceNumber);
                }
                message = await messageReceiver.PeekAsync();
            }

            Console.ReadKey();
            await queueClient.CloseAsync();
        }

Powered by WordPress & Theme by Anders Norén