Deploy click-once application on Azure Blob with Azure DevOps

It was a long time ago I blogged on how to publish a click-once application from a VSTS Build to Azure Blob, long time was passed, and lots of stuff changed. The whole process is now simpler, thanks to many dedicated tasks that avoid doing any manual work.

My new build always start with a  GitVersion custom tasks, that populates some environment variables with version numbers generated by GitVersion, this will allow me to simply add an MsBuild task in the build to publish click-once using automatic GitVersion versioning.


Figure 1: MsBuild task to publish click once application

You need to build the csproj that contains the project, using $(BuildConfiguration) to build in the right configuration and adding custom argument arguments (3) as the following list


ApplicationVersion is set to variable $(AssemblyVersion) that was populated by GitVersion task, publish Url is a simple address of an azure blob storage, that contains a blob container called atest, with a  folder named logviewer that has public read access.


Figure 2: Public read access for a simple blob in my azure subscription

This will allows me to have a simple public blob, with a public address, that everyone can read, so everyone can download my application.

Azure blob can be given a public read access to everyone, making your click-once application available to everyone.

MsBuild task simply creates a app.publish subfolder that contains all the files that needs to be copied into the blob azure storage, the first step is a Copy file Task to copy them in the artifacts directory, as for the following picture.


Figure 3: All files of click-once publishing were copied in the artifacts staging directory.

Now everything is ready, just add a final task of type Azure File Copy and configure to copy everything from artifacts directory to the right subfolder of azure blob.


Figure 4: Configuration of Azure Blob File to deploy click-once generated files.

Configuration is really simple, because thanks to a direct connection to Azure Subscription (3) we can simply connect Azure Dev Ops to an azure subscription so we can simply select storage account (4) blob name (5) and subfolder of the blob (6).

One of the advantage of the dedicated Azure File Copy Task, is that it can simply use one of  the Azure account linked to the Azure DevOps account, making super-simple to choose right blob where to upload click-once package.

Once you’ve finished configuration, you can simply run a build and your application will be automatically published.


Figure 5: Summary of the build with click once publishing.

Now you can simply point to the setup.exe file with the address of the blob and the game is done.

Gian Maria.

Run code coverage for Python project with Azure DevOps

Creating a simple build that runs Python tests written with PyTest framework is really simple, but now the next step is trying to have code coverage. Even if I’m pretty new to Python, having code coverage in a build is really simple, thanks to a specific task that comes out-of-the-box with Azure DevOps: Publish Code Coverage.

In Azure DevOps you can create build with Web Editor or with simple YAML file, I prefer YAML but since I’ve demonstrated in the old post YAML build for Python, now I’m creating a simple build with standard Web Editor

Instead of creating a Yaml Build, this time I’m going to demonstrate a classic build: here is the core part of the build.


Figure 1: Core build to run tests and have code coverage uploaded to Azure DevOps

As you can see, I decided to run test with a Bash script running on Linux, here is the task configuration where I’ve added Pytest options to have code coverage during test run.


Figure2: Configuration of Bash script to run Pytests

The task is configured to run an inline script (1), command line (2) contains –cov options to specify Python modules I want to monitor for code coverage, then a couple of –cov-report options to have output in xml and HTML format. Finally I’ve specified the subfolder that contains the module I want to test (3) and finally I’ve configured the task con Continue on Error (4), so if some of the tests fails the build will be marked as Partially failed.

Thanks to Pytest running code coverage is just a matter of adding some options to command line

After a build finished you can find in the output how Pytest generates Code Coverage reporting, it create a file called coverage.xml then an entire directory called htmlcov that contains a report for code coverage.


Figure 3: Result of running tests with code coverage.

If you look at Figure 1 you can see that the build final task is a Publish Code Coverage Task, whose duty is to grab output of the Pytest run and upload to the server. Configuration is really simple, you need to choose Cobertura as Code coverage tool (the format used by Pytest) and the output of test run. Looking at output of Figure 3 you can double check that the summary file is called coverage.xml and all the report directory is in htmlcov subdirectory.


Figure 4: Configuration for Publish Code Coverage task.

Once you run the build, you can find Code Coverage result on the summary page, as well as Code Coverage Report published as Build artifacts, the whole configuration will take you no more than 10 minutes.


Figure 5: Artifacts containing code coverage reports as well as code coverage percentage are accessible from Build Summary page.

Finally you have also a dedicated tab for Code Coverage, showing the HTML summary of the report


Figure 6: Code coverage HTML report uploaded in a dedicated Code Coverage tab in build result

Even if the code coverage output is not perfectly formatted you can indeed immediately verify percentage of code coverage of your test.

Gian Maria.

Set new Azure DevOps url for your account

Due to switching from the old url format to it is a good practice to start transition to the new url as soon as possible. The old url will continue to function for a long time, but the new official domain is going to become the default.

Every user can still use both the new or old domain name, but there is a settings in the general setting page of the account that globally enable the new url.


Figure 1: New url format enabled in global settings.

Actually there are small parts of the site that does not work perfectly if you browse Azure DevOps with the url not configured in that settings. This is often due to security restriction especially for Cross Site Origin. As an example I got problem with the new url in the release page, because some of the script will be still served with and they got blocked due to CORS


Figure 2: Cross origin request blocked due to security plugin.

This will prevent me to correctly use the new address. After you switch to the new url with the settings shown in Figure 1: The problem is gone.

This setting will also made a redirect to the new url, whenever one is typing they will be redirected to the new url, thus enforcing the usage of the new url automatically.

Gian Maria.

Run Python test with Azure DevOps pipeline

The beauty of Azure DevOps is it support to many technologies and all of major language.s I have a simple git repository where I’m experimenting Python code, in that repository I have several directories like 020_xxxx 010_yyy where I’m playing with Python code.

Each folder contains some code and some unit tests written in Pytest, my goal is creating an Azure Pipeline that can automatically run all pytest for me automatically each time I push some code to the repository.

Even if Phyton is a script languages, it has several Unit Testing frameworks that can be used to verify that the code you wrote works as expected

Creating a build in Azure DevOps is really simple, just create a build that points to a yaml file in your repository that contains the definition.

  name: Hosted Linux Preview

- master
- develop
- features/*
- hotfix/*
- release/*


- task: UsePythonVersion@0
  displayName: 'Use Python 3.x'

- bash: |
   pip install pytest 
   pip install pytest-cov 
   pip install pytest-xdist 
   pip install pytest-bdd 

  displayName: 'Install a bunch of pip packages.'

- bash: 'pytest --junitxml=$(Build.StagingDirectory)/010.xml' 
  workingDirectory: '010_CrackingCodeBasic'
  displayName: 'Run test 010'

- bash: 'pytest --junitxml=$(Build.StagingDirectory)/020.xml' 
  workingDirectory: '020_CrackingIntermediate'
  displayName: 'Run test 020'

- task: PublishTestResults@2
  displayName: 'Publish test result /010.xml'
    testResultsFiles: '$(Build.StagingDirectory)/010.xml'
    testRunTitle: 010

- task: PublishTestResults@2
  displayName: 'Publish test result /020.xml'
    testResultsFiles: '$(Build.StagingDirectory)/020.xml'
    testRunTitle: 020

This is a real simple yaml buid definition where I’m simply requiring the usage of python 3.x, then install some packages with pip and finally a series of pytest tests run for each folder. As you can see I specified also the trigger to automatically build all branches typical of GitFlow naming convention.

The trick to have the result of the tests published directly in your build result is using a Pytest option to create a result file with JUNIT xml file format; once you have test result as a JUNIT xml files you can use standard PublishTestResults task to publish results in the build.

After the build completed you can simply looks at the output, if everything is ok the build is Green.


Figure 1: Test results in my build that shows results of my python unit tests.

The build will run all python tests in all of my source code folder, thanks to Pytest that does everything for you, both discovering and run all tests in the folder.

If code does not compile, unit test will fail and you have a failing build.


Figure 2: Not compiling code will lead to a failing build.

The problem with this approach is that the build stops at the very first error, so if an error happens in 010 directory my 020 directory will not be tested because at the very first failed test the execution of the build stopped.

This condition is usually too strict, for unit testing it is usually a better approach to configure the build to continue even if run test failed. To accomplish this, just add continueOnError: true after each bash task used to run tests. With continueOnError equal to true, the build will continue and if some of the test task fails, the build is marked as Partially Failed, and from the summary you can easily check the run that generates the error.


Figure 3: Continue on error true will make the build continue on test error, in the summary you can verify what failed,

The reason why I choose to launch a different Pytest run for each folder and upload each result with a different task is to have separate run in build result.


Figure 4: Test runs are distinct for each folder.

Even if this will force me to add two task for each folder (one for the run and the other for the publish) this approach will give me a different result for each folder so I can immediately understand where is the error.

Gian Maria.

End of life of PHP 5.6, please upgrade to 7 version

Php 5.6 reached end of life support and this means that it will not receive anymore any security update. If you, like me, run a site with WordPress or any other technology based on PHP you should consider moving to PHP 7 as soon as possible. This is needed to avoid having a bad surprise if someone discover a new security bug and he will use to own your site.

In this article you can find some interesting information and you can verify that moving to PHP 7 will probably made your site to go faster.

Since a compromised site can be used to do phishing or to host malicious scripts, it is a good habit keeping up upgrading your WordPress site and PHP version used by your blog.

Gian Maria.