Is it possible to modify a web.config file in one of my projects during a Team Foundation Server build? Inside of my web.config file I have two setting keys: VersionNumber and BuildNumber.
Is it possible to change the value of BuildNumber based on the ID of the build in TFS?
Since you're using TFS 2013 you have an easier option than the old way of modifying the workflow - Use PowerShell.
If you're using the build template TfvcTemplate.12.xaml (which is the new default in TFS 2013), then you have some extra build definition parameters you can set to specify Powershell scripts to run. This way you just write a little bit of powershell code that gets the TFS Build Number (from an environment variable), then finds your web.config file(s) and changes them.
There is a sample script published in the TFS Community Build Extensions project that will do something very similar that you could modify. It finds all AssemblyInfo.cs files, then uses RegEx to modify them to update the build number based on the TFS Build number.
See the sample PS script here: https://tfsbuildextensions.codeplex.com/SourceControl/latest#Scripts/ApplyVersionToAssemblies.ps1
See some docs on how to modify the build to run PowerShell here: http://msdn.microsoft.com/en-us/library/dn376353.aspx
The answer is yes, though it's non-trivial. I've done this in the past using two methods.
Method 1: Use CodeActivities and alter the TFS Build workflow XAML file to include the new CodeActivity as a workflow step.
Here's an article on creating custom workflows with custom code activities (it's a little dated but still relevant):
http://blogs.msdn.com/b/jimlamb/archive/2010/02/12/how-to-create-a-custom-workflow-activity-for-tfs-build-2010.aspx
Basically, you create a new object that inherits from CodeActivity, create properties for your inputs (BuildNumber,VersionNumber, TargetFile), perform your actions on the TargetFile and save it. Then you wire up this new DLL with your activity to the TFS Workflow XAML, injecting your activity in the desired build step (post-build & pre-package in your case I bet to ensure xml transforms are applied).
Method 2:
Tag the desired properties onto the MSBuild invocation inside the TFS XAML file so they are passed in to MSBuild and available for your to use as $(BuildNumber) and $(VersionNumber). Then you can use MSBuild tasks to inject the properties into the file at the right time.
Related
I have a "SOA" styled application, with a single solution containing almost 100 individual projects (which are a solution within them, i.e. they can be run independently). I have created a build and release definition in TFS 2018 and everything works perfectly.
The issue is if I make changes to a single service (out of 100), and check-in my code, the build definition is triggered which builds the entire application and then the release definition deploys the entire thing(100+) each time.
I don't want it. I need it to be specific to the service in which changes are made. Is there any way to do it?
Creating multiple build/release definition which is tied to the specific path of each service should solve it but I don't want to go down that road, because I will end up creating 100's of definitions.
Is there any other way to do it?
This is for a .Net application, hosted in TFS 2018 (On-premise).
The solution structure is as below:
AllWCFService.sln
|_Service1.csproj
|_Service2.csproj
|..
|..
|_Service100.csproj
Each Service can also be run and hosted independently.
This is my first question here. I apologize for any confusion.
As you have mentioned, by using Path filters on the Build definition should be the easiest solution.
With the proper path to the project in the Path filter only the proper Builds spin up, and any projects untouched do not trigger a build. Each build has it's own release which then deploys the specified app to it's own destination. As a ugly workaround, you could set up a group each with 5 services which will reduce 100's of definitions to 20's.
Otherwise, you have to customize your build definition/pipeline. Use some scripts to determine or judge which part of your Servicex.csproj changed base on your name.
Then call msbuild with /t option to build a single or multiple projects.
msbuild test.sln /t:project;project2 /p:Configuration="Release" /p:Platform="x86" /p:BuildProjectReferences=false
specify project file of a solution using msbuild
It will only build specified changed project and generated corresponding artifacts. Then add scripts in release to specify path according build generated artifacts to deploy each service.
Hope this helps.
Trying to get any TFS build definition to come pre-equipped with nuget restore so we can get the packages folder out of source control, but don't have a way to make sure these steps are at the beginning of every new build definition automatically. Any ideas?
You can't force it. You can encourage people to use templates (either the out-of-the-box templates or templates you create yourself), but you can't say "only allow users to create build definitions based on templates".
The default build template for TFS has a format of $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)
This translates to something like BuildName_20141111.1 for the first build of the day, BuildName_20141111.2 for the second and so on that.
That's all well and good but what I'd like to do is pull out that .r and insert it into the assembly before it's compiled by the build server.
I've already edited the build template to update the various AssemblyInfo.cs files and such and that's working fine. Right now we are toying with the idea of Major.Minor.yyDDD (Day of year).r but the catch is that very last part - how do we get $(Rev:.r) from within a build template?
I've tried looking through the various environmental variables and I can pull out the entire Build definition string (i.e. BuildName_20141111.1) but really all I want is that .1 (or more specifically "1"). Is there a way to do this programmatically? Is there an environment variable I've missed? Or is there a way that I can actually access things like $(Rev:.r) directly?
I am relatively new to TFS but this is the last hurdle before I can move a lot of projects to it.
You effectively need to parse this off yourself from the BuildName parameter. If you are using TFS 2013 you can do it in PowerShell. Prior versions need a customized build template.
There are prebuilt solutions to this. Best is the TfsVersion activity or the VersionAssemblies.ps1 that is provided as part of the TFS Community Build Tools.
When we used TFS 2008 (SP1) we used to be able to access the "Reason" MSBuild property, which contained the reason the build was running. This was available as soon as the build started, so no task/target needed to fetch it. Now we're using TFS 2010 (and MSBuild / Upgrade Template, not Workflow) and the property is no longer populated. I could write a custom task to retrieve the info from IBuildDetail, but isn't there a property immediately available to my MSBuild scripts? I used to be able to do conditional MSBuild script imports based on the build reason and this will not work if I have to use a task/target to fetch the reason.
You are still using MSBuild scripts, so I assume you are using the Upgrade Template. You can clone/edit or modify the Upgrade Template so that the template takes the current build reason and passes it to MSBuild via the Run TfsBuild for Configuration Folder activity. Open the template for edit in Visual Studio and do the following:
Select the Run On Agent activity and go to the Variables tab. Create a new variable to store the build reason and populate its default value using info from the IBuildDetail. Add something like the following to the list of variables:
Name: currentBuildReason
Variable type: String
Scope: Run On Agent
Default: BuildDetail.Reason.ToString()
Next, click on the Properties dialog for the Run TfsBuild for Configuration Folder activity. Select the CommandLineArgument elipses to open the dialog that passes arguments to TFSBuild. You probably only see one variable listed:
MSBuildArguments
You can now add the current build reason to the command line arguments (and still pass any existing MSBuildArguments), similar to this:
String.Format("/p:CurrentBuildReason={0} {1}", currentBuildReason, MSBuildArguments)
Click OK to close the dialog. That will pass the current build reason as a new argument named CurrentBuildReason and it can be referenced as $(CurrentBuildReason) in your MSBuild scripts.
Save and check-in the Upgrade Template.
Assign the template to a Build Definition. The MSBuild scripts used by that definition can now use the variable as described above.
We are using TFS Build 2010 for Builds. We have two branches of source code (Lets say branchA and branchB).
Now as a part of the build definition we set the projects to build:
Now to employ the same build definition from branchB will mean that I create another build definition file with same content, with only the items to build set to "$/branchB"
Is there anyway to make this configurable, without having to edit the build definition?
Also there are other input variables that we set for the build definition, and the values for these variables are included in the build definition XAML file. So to change the value of a variable will mean that we have to edit the build definition XAML file. This is not desirable.
I would like to be able to set the "Items to Build" and the variables of the build definition without having to modify the build definition XAML file.
Are there any solutions to these problems?
You can modify the Build Process Template so it only asks you for the Items to Build. The rest of the arguments are prefilled. To get an idea how this works, see http://www.ewaldhofman.nl/?tag=/build+2010+customization
You can add parameters to your build definition. I did this a while back because we had two web projects in a solution that had to be deployed to different servers (via Windows shares). I added parameters to the build def so that in the build properties I could customize them depending on if it was a dev deployment, staging, etc.
I added a blog post on how to do it. You can use the parameters this way so that they aren't kept in the XAML file.
Deploying Web Apps with a customized Build Process in TFS