But it works on my PC!

The random thoughts of Richard Fennell on technology and software development

Fix for ‘An unexpected error occurred. Close the windows and try again’ error adding Azure subscription to Visual Studio Release Management Tools

In preparation for my Techdays session next month, I have been sorting demos using the various Release Management clients.

When I tried to create a release from within Visual Studio using the ‘Release Management tools for Visual Studio I found I could not add my Azure subscriptions. I saw the error ‘An unexpected error occurred. Close the windows and try again’

image

I could download and import the subscription file, it showed the available storage accounts, but when I pressed save I got the rather unhelpful error ‘Object reference not set to an instance of an object’

image

Turns out the issue was a simple one, rights. The LiveID I had signed into Visual Studio as had no rights for Release Management on the VSO account running the Release Management service, even though it was a TPC administrator.

It is easier to understand the problem in the Release Management client. When I tried to set the Release Management Server Url (RM > Administration > Settings) to the required VSO Url as the LiveID I was using in Visual Studio I got the nice clear error shown below.

image

The solution was in the Release Management client to use the LiveID of the VSO account owner. I could then connect the Url in the Release Management client and then add my previously failing LiveID as a user for the release service.

image

Once this was done I was able to use this original LiveID in Visual Studio without a problem.

VSO gets ISO 27001 Certification and European Model Clauses

If the reason you have not been using VSO was concern over where it is hosted, then last week Microsoft made an announcement that could ease some of your worries, or at least your legal departments.  VSO now has ISO 27001 Certification and European Model Clauses; for more details see Brian Harry’s blog.

This added to the fact that since the end of last October you have been able to choose to host your VSO instance in Europe could well make VSO a more compelling option for many organisations who don’t want to have their own TFS servers on premises

Speaking at Microsoft Techdays on the 5th of February

On the 5th of February I will be presenting at Microsoft’s online Techdays event. My session is entitled ‘How are you going to deploy that? A look at configuration as code’

“It does not matter what platform you are developing for, you are going to have to deploy your product in the end. Too often in the past the question of deployment has been an afterthought. But it need not be this way, there are tools available that can help with deployment of your code and importantly the provisioning the underlying systems they need too. In this session we will look at Visual Studio Release Management’s vNext release pipeline seeing how it can leverage Desired State Configuration to provision environments and deploy applications”

There an loads of great sessions spread cross the three days of this online conference, why not register for the event online now? I am sure there will be something of interest.

How to edit registered Release Management deployment agent IP addresses if a VMs IP address changes

I have posted in the past that we have a number of agent based deployments using Release Management 2013.4 that point to network isolated Lab Management environments. Over Christmas we did some maintenance on our underlying Hyper-V servers, so everything got fully stopped and restarted. When the network isolated environment were restarted their DHCP assigned IP addresses on our company domain all changed (maybe we should have had longer DHCP lease times set?)

image

Worst of all some were reused and were actually swapped between environments, so an IP address that used to connect to a Server1 in environment Lab1 could be assigned to Server2 in environment Lab2. So basically all our deployments failed, usually because there server could not connect to the agent, but sometimes because the wrong VM responded.

Now for general Lab Management operations this was not an issue; inside the environment nothing had changed, the network range was still 192.168.23.x and externally SCVMM, MTM and the Test Controllers all knew what is going on and sorted themselves out. The problem was the Release Management deployment agent’s registration with the Release Management server. As I detailed in my previous post you have manually register the agents using shadow accounts. This means they are registered with their IP address at the time of registration, it does not change if the VMs IP address is reassigned with DHCP. It is up to you to fix it.

But how?

And that is the problem, there is no way to edit the IP addresses of the registered server’s deployment agents inside the Release Management admin tool. The only option I could find would be deleted the registered server and re-add them, but this requires them to be removed from any release pipelines. Something I did not want to do, to much work when I just wanted to fix an IP address.

The solution I found was to edit the IPAddress column in the underlying Server table in the ReleaseManagement DB. I did this with SQL Management Studio, nothing special. The only thing to note is that you cannot have duplicate IP addresses, so they had to be edited in an order to avoid duplication, using a temporary IP address during the edit process as I shuffled addresses around.

image

Once this was done everything leapt into life. I did not even need to restart the Release Management Server, just press the refresh button on the Server tab and saw all the agents had reconnected.

image

So a good dirty fix, but something I would have hoped would have been easier if the tools provided a means to edit the IP addresses

Note: This problem is specific to agent based deployment in Release Management. If you are using vNext DSC based deployment to network isolated VMs are registered using their DNS names on the corporate LAN e.g. VSLM-1344-e7858e28-77cf-4163-b6ba-1df2e91bfcab.lab.blackmarble.co.uk so the problem does not occur

vNext Release Management and Network Isolation

If you are trying to use Release Management or any deployment tool with a network isolated Lab Management setup you will have authentication issues. Your isolated domain is not part of your production domain, so you have to provide credentials. In the past this meant Shadow Accounts or the simple expedient of  running a NET USE at the start of your deployment script to provide a login to the drops location.

In Release Management 2013.4 we get a new option to address this issue if you are using DSC based deployment. This is Deploy from a build drop using a shared UNC path. In this model the Release Management server copies the contents of the drops folder to a known share and passes credentials to access it down to the DSC client (you set these as parameters on the server).

This is a I nice formalisation of the tricks we had to pull by hand in the past. And something I had missed when the Update 4 came out

Thoughts in vNext deployment in Release Management

The DCS two step

When working with DSC a difficult concept can be that your desired state script is ‘compiled’ to a MOF file that is then ‘run’ by the desired state manager on the target machine. This is a two step affair and you have no real input on the second part. This is made more complex when Release Management is involved.

Colin Dembovsky did an excellent pair of posts on getting Release Management working with DSC based vNext templates. The core of the first post is that he made use of the Script DSC resource to run SQLPackage.EXE and MSDeploy to do the actual deployment of a system as well as using it to manage the transformation of the configuration files in his MSDeploy package.

This is where the two step issue raises it head. Even with his post I managed to get myself very confused.

The problem is Release Management passes variable into the DSC script and these are evaluated when the MOF is compiled. For most resources this is fine, but for the Script resource you have to be very aware that the string that is the actual script is treated as just a string, not code, so variables are not evaluated until the MOF is run by the desired state manager, by which point there are no Release Management variables set (they are long gone).

Colin’s provides an answer to this problem with his cScriptWithParams resource. This resource takes the Release Management provided properties and passes them into as parameters into the MOF compilation, forcing their evaluation, neatly side stepping the problem. He uses this  technique for the SetParameters.XML transform.

This is all good, but it got me thinking, his post has a number of hard coded paths, and also copies the deployment files to a ‘known location’. Is this really all required if we can pass in the Release Management $ApplicationPath?

So I swapped all my Script resources to use the cScriptWithParams resource passing in the applicationpath thus removing the need to copy the files from their default location.

      cScriptWithParams SetConStringDeployParam
        {
            GetScript = { @{ Name = "SetDeployParams" } }
            TestScript = { $false }
            SetScript = {
                $paramFilePath = "$folder\_PublishedWebsites\WcfService_Package\WcfService.SetParameters.xml"
 
                $paramsToReplace = @{
                      "__DBContext__" = $context
                      "__SiteName__" = $siteName
                }
 
                $content = gc $paramFilePath
                $paramsToReplace.GetEnumerator() | % {
                    $content = $content.Replace($_.Key, $_.Value)
                }
                sc -Path $paramFilePath -Value $content
            }
            cParams =
            @{
                context = $context;
                siteName = $siteName;
                folder = $ApplicationPath;

            }
        }

       
        cScriptWithParams DeploySite
        {
            GetScript = { @{ Name = "DeploySite" } }
            TestScript = { $false }
            SetScript = {
                & "$folder\_PublishedWebsites\WcfService_Package\WcfService.deploy.cmd" /Y
            }
           
            cParams =
            @{
                folder = $ApplicationPath;
            }

            DependsOn = "[cScriptWithParams]SetConStringDeployParam"
           
        }

I think this gave a easier to follow script, though I do wonder about my naming convention, maybe I need to adopt a nomenclature for inner script variables as opposed to global ones

Where are my parameters stored?

However, this does raise the question of where do these ‘global’ parameters come from? We have two options

  • A PowerShell Configuration data file (the standard DSC way)
  • Release management parameters

Either are valid, if you want to source control all  your configuration the first option is good. However what happens if you need to store secrets? In this case the ability to store a value encrypted within Release Management is useful.

In reality I expect will will use a combination. maybe with everything bar secrets in the configuration file.

Setting a build version in a JAR file from TFS build

Whilst helping a Java based team (part of larger organisation that used many sets of both Microsoft and non-Microsoft tools) to migrate from Subversion to TFS I had to tackle their Jenkins/Ant based builds.

They could have stayed on Jenkins and switched to the TFS source provider, but they wanted to at least look at how TFS build would better allow them to  trace their builds against TFS work items.

All went well, we setup a build controller and agent specifically for their team and installed Java onto it as well the TFS build extensions. We were very quickly able to get our test Java project building on the new build system.

One feature that their old Ant scripts used was to store the build name/number into the Manifest of any JAR files created, a good plan as it is always good to know where something came from.

When asked as how to do this with TFS build I thought ‘no problem I will just use TFS build environment variable’ and add something like the following

<property environment="env"/>

<target name="jar">
        <jar destfile="${basedir}/javasample.jar" basedir="${basedir}/bin">
            <manifest>
                <attribute name="Implementation-Version" value="${env.TF_BUILD_BUILDNUMBER}" />
            </manifest>   
        </jar>
</target>

But this did not work, I just saw the text ${env.TF_BUILD_BUILDNUMBER}" in my manifest, basically the environment variable could not be resolved.

After a bit more of think I realised the problem is that the Ant/Maven build extensions for TFS are based on TFS 2008 style builds, the build environment variables are a TFS 2012 and later feature, so of course they are not set.

A quick look in the automatically generated TFSBuild.proj file generated for the build showed that the MSBuild $(BuildNumber) was passed into the Ant script as a property, so it could be referenced in the Ant Jar target (note the brackets change from () to {})

<target name="jar">
        <jar destfile="${basedir}/javasmaple.jar" basedir="${basedir}/bin">
            <manifest>
                <attribute name="Implementation-Version" value="${BuildNumber}" />
            </manifest>   
        </jar>
</target>

 

Once this change was made I then got the manifest I expected including the build number

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.4
Created-By: 1.8.0_25-b18 (Oracle Corporation)
Implementation-Version: JavaSample.Ant.Manual_20141216.7

Can’t build SSDT projects in a TFS build

Whilst building a new TFS build agent VM using our standard scripts I hit a problem that SSDT projects would not build, but was fine on our existing agents. The error was

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets (513): The "SqlBuildTask" task failed unexpectedly.
System.MethodAccessException: Attempt by method 'Microsoft.Data.Tools.Schema.Sql.Build.SqlTaskHost.OnCreateCustomSchemaData(System.String, System.Collections.Generic.Dictionary`2<System.String,System.String>)' to access method 'Microsoft.Data.Tools.Components.Diagnostics.SqlTracer.ShouldTrace(System.Diagnostics.TraceEventType)' failed.

The problem was fixed by doing an update via the Visual Studio > Tools > Extensions and Updates. Once this was completed the build was fine.

Seems there may have been an issue with the Update 3 generation SSDT tools, so older and newer versions seem OK. Our existing agents had already been patched.

TFS announcements roundup

There have been a load on announcements about TFS, VSO and Visual Studio in general in the past couple of week, mostly at the Connect() event.

Just to touch on a few items

If you have not had a chance to have look at these features try the videos of all the sessions on Channel9, the keynotes are a good place to start. Also look, as usual, at the various posts on Brian Harry’s Blog. It is time of rapid change in ALM tooling

Errors running tests via TCM as part of a Release Management pipeline

Whilst getting integration tests running as part of a Release Management  pipeline within Lab Management I hit a problem that TCM triggered tests failed as the tool claimed it could not access the TFS build drops location, and that no .TRX (test results) were being produced. This was strange as it used to work (the RM system had worked when it was 2013.2, seems to have started to be issue with 2013.3 and 2013.4, but this might be a coincidence)

The issue was two fold..

Permissions/Path Problems accessing the build drops location

The build drops location passed is passed into the component using the argument $(PackageLocation). This is pulled from the component properties, it is the TFS provided build drop with a \ appended on the end.

image 

Note that the \ in the text box is there as the textbox cannot be empty. It tells the component to uses the root of the drops location. This is the issue, as when you are in a network isolated environment and had to use NET USE to authenticate with a the TFS drops share the trailing \ causes a permissions error (might occur in other scenarios too I have not tested it).

Removing the slash or adding a . (period) after the \ fixes the path issue, so..

  • \\server\Drops\Services.Release\Services.Release_1.0.227.19779        -  works
  • \\server\Drops\Services.Release\Services.Release_1.0.227.19779\      - fails 
  • \\server\Drops\Services.Release\Services.Release_1.0.227.19779\.     - works 

So the answer is add a . (period) in the pipeline workflow component so the build location is $(PackageLocation). as opposed to $(PackageLocation) or to edit the PS1 file that is run to do some validation to strip out any trailing characters. I chose the later, making the edit

if ([string]::IsNullOrEmpty($BuildDirectory))
    {
        $buildDirectoryParameter = [string]::Empty
    } else
    {
        # make sure we remove any trailing slashes as the cause permission issues
        $BuildDirectory = $BuildDirectory.Trim()
        while ($BuildDirectory.EndsWith("\"))
        {
            $BuildDirectory = $BuildDirectory.Substring(0,$BuildDirectory.Length-1)
        }
        $buildDirectoryParameter = "/builddir:""$BuildDirectory"""
    }
   

Cannot find the TRX file even though it is present

Once the tests were running I still had an issue that even though TCM had run the tests, produced a .TRX file and published it’s contents back to TFS, the script claimed the file did not exist and so could not pass the test results back to Release Management.

The issue was the call being used to check for the file existence.

[System.IO.File]::Exists($testRunResultsTrxFileName)

As soon as I swapped to the recommended PowerShell way to check for files

Test-Path($testRunResultsTrxFileName)

it all worked.