VSTS Task that changes project files and checks in the changes

147 Views Asked by At

With TFS 2015, we had made a vNext (VSTS) task that would find a selected file, substitute a token (version number is where it started,) wrote out the changes to the file, and checked the file in with a comment as to the nature of the change. It did this all through automation during the build process.

We are about to upgrade to DevOps 2020 and the TFS management tools from 2015 were deprecated, which in itself would be fine, however, we still need to automate these file changes during the build process, including the check-ins noting the nature of the change.

The old task fails miserably ported over directly. I have re-written the process as a C# console app project and planned to call it during a PowerShell script, but I am encountering a number of road blocks to this plan.

What I have done so far.

  1. I have written a task.json for the VSTS task that accepts parameters that it passes to a PowerShell script.

  2. I have written a PowerShell script that call a C# console application to both locate and change the tokens in the file(s) as specified by the task. After changing the file content, it overwrites the original file.

I appear to have two issues that, as yet, I am unable to solve.

  1. I am expecting (if task parameters dictate,) to alter the pipeline environment variable $env:BUILD_BUILDNUMBER to a new value, from the C# code. I am using the following C# command using the third parameter expecting that this will allow the pipeline to see the changes it has made to the variable: Environment.SetEnvironmentVariable("BUILD_BUILDNUMBER", buildNumber, EnvironmentVariableTarget.Machine ); (I have also tried without the parameter and also User and Process, to no avail.) The variable will not 'set' for the pipeline to see outside of the console app.
  2. I need to check the changes made in step 2 from the C# code, back into the code repository with a short comment. The initial 'Get' that the pipeline does calls tf, but I have not had the same success. I have found that if I call VS2019's copy of tf.exe or the agents copy in 'externals' on the build machine, whether from C# or from the later PowerShell script, I get "##[error]Unable to determine the workspace. You may be able to correct this by running 'tf workspaces /collection:TeamProjectCollectionUrl'" Needless to say, this later instruction to run tf workspaces does not help out.

I am hoping these things have simple solutions. I have searched for, but not found an API call to DevOps 2020 that will check in the code. Perhaps that does not exist. As for the Environment Variable, I am at a little bit of mystery as to why the EnvironmentVariableTarget.Machine is not working. I suspect it has something to do with the ##vso[] method not being called but I am unsure of how to pass out my findings from the console app (which also needs to return 0 for success, else failure,) to the PowerShell script that can change the variable more easily.

If there are any bright ideas out there about this, I would really appreciate the insight you might lend. I have been at this for a while and I am not sure what else to consider to make this work.

1

There are 1 best solutions below

0
On BEST ANSWER

Using TFVC rather than Git, and a multitude of other little legacy technology items, makes working with the new tools a bit harder to figure out as it was in this case.

So my first problem item, updating the environment Build Number in the build tasks before the build starts. I was able to set the variable from my C# code, by opening a PowerShell process that takes an argument to update the variable with the ##vso[Build.UpdateBuildNumber] function in PowerShell. The C# code to do this looks like the following:

        var ps = @$"C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe";
        var script = $@"SetEnvironmentBuildNumber.ps1";
        if (File.Exists( script )){
            if ( File.Exists( ps ) )
            {
                await Task.Run( () =>
                {
                    var scriptWithArguments = string.Concat( Path.Combine( Directory.GetCurrentDirectory(), script ), " -newBuildNumber ", newBuildNumber);
                    Process.Start( ps, scriptWithArguments );

                } );
            }
            else
            {
                Console.WriteLine( $"PowerShell File Not found at: {ps}" );
            }
        }
        else
        {
            Console.WriteLine( $"The current directory is: {Directory.GetCurrentDirectory()}");
            Console.WriteLine($"Script File Not found at: {script}");
        }

The PowerShell script in SetEnvronemntBuildNumber.ps1 looks like this:

[CmdletBinding()]
param(
[string][Parameter(Mandatory=$true)]$newBuildNumber
)
Write-Host( "Setting the new build number - " + $newBuildNumber )
Write-Host( "##vso[Build.UpdateBuildNumber]$newBuildNumber" )

As it turns out, this exercise helped me understand the Undetermined Workspace, my problem #2.

If you look at the if statements of my C# code, you'll note a check to see just what directory is the current working directory. Finding out that my new task changed the current working directory to the location of my Task and not the pipeline's working directory gave me reason to pause.

Even though, I fall out of the C# code, back into my PowerShell script, I am not looking at the solution's directory, I am looking at the Task directory. If I call tf from this view, there is no source code, and hence no way to determine the WorkSpace.

The solution was simple, there is a pipeline System environment variable that will get me back home, so to speak. Calling the PS Set-Location as below, just before I call tf vc checkin... allowed tf to find the Workspace and save my changes.

Set-Location $env:System_DefaultWorkingDirectory

This was all it took, all these tweaks were innocent enough, but very troublesome to diagnose without any formal training in the ways of the DevOps pipeline. I look forward to more 'fun' with DevOps, when we try to figure out how to get to Git from TFVC... I am sure not all our legacy will see such significant changes.

Thanks for the suggestions, and I hope this can help some other poor soul trapped in a legacy world and trying to get out of the hole.