TFS Build 2.0 C#, howto add variables to the build/Pass Msbuild args
Asked Answered
K

4

5

I am trying to pass arguments to MSBuild 2.0. After research it appears that I need to do this using variables, but I cannot figure out how to incorporate this into my queue request below. I have tried parameters but that does not seem to work. Here is what I am trying to tell MSBuild @" /p:OctoPackPackageVersion=" + releaseNumber. This worked with the XAML build using IBuildRequest.ProcessParameters.

var buildClient = new BuildHttpClient(new Uri(collectionURL), new 
VssCredentials(true));
var res = await buildClient.QueueBuildAsync(new Build
            {
                Definition = new DefinitionReference
                {
                    Id = targetBuild.Id
                },
                Project = targetBuild.Project,
                SourceVersion = ChangeSetNumber,
                Parameters = buildArg

            });
            return res.Id.ToString();
Kadner answered 27/6, 2017 at 15:59 Comment(3)
Which build are you using now, XAML or vNext ? Did you mean you could not figure out how to use this on vNext build?Ghent
Patrick, we have switched our definitions from XAML to scriptable(introduced with TFS 2015). When we used the XAML build definition I used IBuildRequest.ProcessParameters to pass in the octo build arg I listed above which worked, however I do not know how to pass that in with the scriptable builds. In the code above I try to pass that into the parameters field but the build succeeds but does not seem to look at that parameter. I tried using other fields in the link below but those do not work either. visualstudio.com/en-us/docs/build/define/optionsKadner
What's the useage of the queue request ? Did you just want to pass the octo version Parameter? Could you use some scripts? Details about variables please see my answer below.Ghent
M
4

vNext build system is different with legacy XAML build system, you cannot pass variable to build tasks in the build definition directly when queue the build. The code you used updated the build definition before queue the build which means that the build definition may keep changing if the variable changed.

The workaround for this would be add a variable in your build definition for example "var1" and then use this variable as the arguments for MSBuild Task: enter image description here With this, you will be able to pass the value to "var1" variable when queue the build without updating the build definition.

Build build = new Build();
build.Parameters = "{\"var1\":\"/p:OctoPackPackageVersion=version2\"}";

// OR using Newtonsoft.Json.JsonConvert
var dict = new Dictionary<string, string>{{"var1", "/p:OctoPackPackageVersion=version2"}};
build.Parameters = JsonConvert.SerializeObject(dict)
Meshed answered 29/6, 2017 at 3:9 Comment(1)
Awesome, I knew there was something I was missing. Thanks Eddie, this worked perfectly.Kadner
N
2

I have found this solution and it works for me excellent. I set custom parameters for convenience in build definition without updating on server:

foreach (var variable in targetBuildDef.Variables.Where(p => p.Value.AllowOverride))
        {
            var customVar = variables.FirstOrDefault(p => p.Key == variable.Key);
            if (customVar == null)
                continue;
            variable.Value.Value = customVar.Value.TrimEnd('\\');
        }

And then set variables values in build parameters:

        using (TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri(tFSCollectionUri)))
        {
            using (BuildHttpClient buildServer = ttpc.GetClient<BuildHttpClient>())
            {
                var requestedBuild = new Build
                {
                    Definition = targetBuildDef,
                    Project = targetBuildDef.Project
                };
                var dic = targetBuildDef.Variables.Where(z => z.Value.AllowOverride).Select(x => new KeyValuePair<string, string>(x.Key, x.Value.Value));
                var paramString = $"{{{string.Join(",", dic.Select(p => $@"""{p.Key}"":""{p.Value}"""))}}}";
                var jsonParams = HttpUtility.JavaScriptStringEncode(paramString).Replace(@"\""", @"""");
                requestedBuild.Parameters = jsonParams;
                var queuedBuild = buildServer.QueueBuildAsync(requestedBuild).Result;
Netta answered 12/10, 2018 at 10:34 Comment(0)
G
0

First, the new build on TFS2015 which is called vNext build not MSbuild 2.0.

Which you are looking for should be Build variables. Variables give you a convenient way to get key bits of data into various parts of your build process. For the variable with Allow at queue time box checked you could be enable allow your team to modify the value when they manually queue a build.

Some tutorials may be helpful for using variables:

Ghent answered 28/6, 2017 at 13:0 Comment(2)
Thanks Patrick, yes as I mentioned above I saw that this needs to be passed in using variables, but I am not sure how to do in c# not powershell. I have added it to the build def specification as queue time but I am not sure how to pass this variable into QueueBuildAsync. I looked through the documentation and I could not find this either.Kadner
@KiritChandran I'm not pretty sure which arguments you want to pass. Did you just want to queue a build from C#? Besides if you are using QueueBuildAsync with old TFS API the same as XAML build. I'm afraid this will not work on vNext build. Maybe this is the root cause. You need to use Rest API, take a look at this tutorial How to trigger a build in TFS 2015 using REST API& tech.en.tanaka733.net/entry/…Ghent
K
0

Patrick, I was able to find a work around to my issue by updating the build definition. This is definitely not ideal but it works. As you can see below I am trying to add to the msbuild args already present. If you know a better way let me know. I really appreciate you taking the time to look at my question.

 public static async Task<string> QueueNewBuild(string project, BuildDefinitionReference targetBuild, string collectionURL, string ChangeSetNumber, string ReleaseNumber, bool CreateRelease)
    {
        var buildClient = new BuildHttpClient(new Uri(collectionURL), new VssCredentials(true));
        await Task.Delay(1000).ConfigureAwait(false);
        var buildDef = await buildClient.GetDefinitionAsync(targetBuild.Project.Id, targetBuild.Id);
        BuildDefinitionVariable OrigMSbuildvar = buildDef.Variables["MSBuildArgs"];
        buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value + " /p:OctoPackPackageVersion=" + ReleaseNumber.ToString();

        await Task.Delay(1000).ConfigureAwait(false);
        buildDef = await buildClient.UpdateDefinitionAsync(buildDef);

        await Task.Delay(1000).ConfigureAwait(false);
        Build build = new Build
        {
            Definition = new DefinitionReference
            {
                Id = targetBuild.Id
            },
            Project = targetBuild.Project,
            SourceVersion = ChangeSetNumber
        };

        await Task.Delay(1000).ConfigureAwait(false);
        var res = await buildClient.QueueBuildAsync(build);
        buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value;           
        await Task.Delay(1000).ConfigureAwait(false);
        buildDef = await buildClient.UpdateDefinitionAsync(buildDef);
        return res.Id.ToString();

    }
Kadner answered 28/6, 2017 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.