How to correctly get TFS changeset number into Project Version field of SonarScanner on Jenkins? - jenkins

We are running Jenkins as our build server and on-prem TFS as our source control. We are using SonarScanner for MSBuild step before the build, and one of the fields which can be populated is "project Version". The value in this field will tag the sonar analysis with the version.
I have tried the following values:
$TFS_CHANGESET
${TFS_CHANGESET}
${ENV,var="TFS_CHANGESET"}
but unfortunately I just get the literal text that is put in, not an evaluation of the environment variable.
Is there a way to get the actual environment variable evaluated and it's value used instead? The sonarqube scanner documentation does not appear to provide information on how to use environment variables, and the various posts I have read, leading to the values I have tried do not appear to work either!
Ref:
https://community.sonarsource.com/t/expand-environment-variables-in-sonarqube-scanner-for-jenkins/4711

How to correctly get TFS changeset number into Project Version field of SonarScanner on Jenkins?
If you are using the default way to download your code from Azure DevOps Server by through the usage of the Source Code Management Tab, it seems we could not configure it to download the source code by a particular changeset number.
To resolve this issue, you could use Windows batch command to get the latest source code:
%TFS% workspaces -format:brief -server:{your-tfs-team-project-collection-url}
%TFS% workspace -new Hudson-%JOB_NAME%-MASTER;{your-domain-user-name} -noprompt -server:{your-tfs-team-project-collection-url}
%TFS% workfold -map $/{tfs-path-to-your-sln} C:\Jenkins\jobs\%JOB_NAME%\workspace\ -workspace:Hudson-%JOB_NAME%-MASTER -server:{your-tfs-team-project-collection-url}
%TFS% get $/{tfs-path-to-your-sln} -force -recursive -noprompt
%TFS% history $/{tfs-path-to-your-sln} -recursive -stopafter:1 -noprompt -format:brief -server:{your-tfs-team-project-collection-url}
Please check the document Jenkins: Get Source Code By Specific TFS Changeset for some more details.
Hope this helps.

Related

TFS tf branch command error: no appropriate mapping exists for

I'm trying to use tf branch, but get this error:
no appropriate mapping exists for $/main_folder/folderB/folder1
below is my command:
tf branch $/main_folder/folderA/folder1/file.sql $/main_folder/folderB/folder1
Any ideas why?
The branch command copies an item or set of items, including metadata and version control history, from one location to another in the Team Foundation version control server and in the local workspace.
According to above error info, you also need to map your $/main_folder/folderB/folder1 path to your local workspace. Then try to perform the command again.
More detail tutorial about how to use this command please refer this official tutorial: Branch Command
A sample full command in cmd with using tf.exe branch command for your reference:
tf branch $/ScrumProject/TestCaseProject $/ScrumProject/Test /w:WPATRICK-W10

How to use the Jenkins MSBuild plug-in in a Jenkinsfile?

I have Jenkins v2.60.3 with the MSBuild Plugin v1.27 installed on Windows.
I have configured the path to my msbuild.exe in Jenkins' Global Tool Configuration. I have also setup a Multi Branch Pipeline in Jenkins that picks up a Jenkinsfile from git repo successfully.
My question is: How do I invoke the MSBuild Plugin as a step in my Jenkinsfile?
Please note I know I can invoke msbuild.exe directly as a Windows batch step but I prefer to go through the MSBuild Plugin if possible.
`
It looks like MSBuild is not supported by pipeline yet
https://github.com/jenkinsci/pipeline-plugin/blob/master/COMPATIBILITY.md
You can try this in the meantime.
https://github.com/jenkinsci/pipeline-examples/blob/master/jenkinsfile-examples/msbuild/Jenkinsfile
Our teams need to migrate a ton of freestyle MSBuild jobs that were created in the UI. mjd's answer helped but still left me scratching my head. The examples just didn't work... until I figured out the disconnect.
Here's the secret sauce:
You have to call the "named msbuild configuration" directly using the
"bat" and "tool" commands.
go into the Config of one of your freestyle jobs that uses the MSBuild plugin
scroll down to the msbuild section and click the "MSBuild Version" drop down, take note of the exact names that are listed. This is your 'named msbuild configuration'. Choose one name that you will use in the next step.
open your jenkinsfile, locate the stage and step where you want to call msbuild, then add this line and replace 'MSBuild 15.0' with the name that you chose in step 2:
bat ""${tool 'MSBuild 15.0'}\\msbuild" SolutionName.sln /p:Configuration=Release /p:Platform="Any CPU" /p:ProductVersion=1.0.0.${env.BUILD_NUMBER}"
like so...
(For Declarative Pipelines, you'll need to put this inside of a "script" block. If you don't know what a 'Declarative Pipeline' is, it is one of two styles of writing pipeline scripts in Jenkins using the "groovy" language. For more info here is a comparison of the scripted vs declarative styles.)
run the pipeline and examine the output - the code you added in step three won't build anything, you just want to use it to see if msbuild will actually get called before investing anymore time into my script.
(I usually use the Replay button which allows me to edit the script online in Jenkins rather than editing, committing, and pushing to remote repo... it just saves a bit of time debugging.)
examine the output of the pipeline job you ran in step 4. You should see something like below indicating that the correct version of MSBuild was called. If not, you either have a typo or your administrator needs to intervene.
workspace\Pipeline_Test>"C:\Program Files (x86)\Microsoft Visual
Studio\2017\Professional\MSBuild\15.0\Bin\msbuild" SolutionName.sln
/p:Configuration=Release /p:Platform="Any CPU"
/p:ProductVersion=1.0.0.308 Microsoft (R) Build Engine version
15.9.21+g9802d43bc3 for .NET Framework Copyright (C) Microsoft Corporation. All rights reserved.
Congratulations you can now configure your build! Replace SolutionName.sln with your build file and pass the correct parameters to it.
I am surprised that all solutions doesn't work for me.
Platform : Window 10 Jenkins at latest version in 2020-11-05.
I am not sure if there's any reason that window & other OS will cause the pipeline script engine behaved differently.
Below are the possible encountered issues and solution finally combined with the above solution.
in my compiler, a single '' will cause error, '' must be escaped by replaced by '\'. which is similar to other char such as '"'
${tool 'MSBuild'} OR ${tool 'MSBuild 15.0'}\msbuild\ does not work, the error is the path cannot specified or cannot find the bat program. It must be an absolute path of the actual msbuild.exe
So this is the working solution for adding MSbuild in the pipeline script in window platform's jenkin
bat '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild" YourSolution.sln /p:Configuration=Release /p:Platform="Any CPU" /p:ProductVersion=1.0.0.${env.BUILD_NUMBER}'

TFS - Getting all the change sets included in the last get

I am creating a batch build script.
I need a tfs cmd command to print all the change sets included in my get.
i failed to google it so far, appreciate any help.
I found a solution.
You can use the tf history command, you can compare the history of the local workbench vs the server.
Try this command:
tf history xxx.sln /noprompt /v:Cxx~W
Cxx: Get the changset of the time you would do the last get.
W: Specifies the version in your workspace.(Current)

Jenkins Build Fails when trying to using MSBuild Extensions - Unable to determine the source control server

I am trying to use Jenkins in combination with MSBuildExtensions and TFS to transform AssemblyInfo.cs
On my dev box, everything works, fine, including the connection to TFS, which returns the changeset number correctly.
When I check in a changeset, and try and build on the Jenkins server, I get an error and the build breaks on this command:
Resolve TF.exe path
TF.exe path resolved to: C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\..\IDE\tf.exe
TF Operation: GetChangeset
Executing C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\..\IDE\tf.exe changeset /login:myDomain\SomeUser,myPassword /latest /noprompt
C:\Program Files\Jenkins\jobs\DemoVersioning\workspace\VersioningDemo\VersioningDemo.csproj(513,3): error : Exit Code 100. Nothing Succeeded: Unable to determine the source control server.
In my msbuild script, this is the TFS command I am running on "BeforeBuild":
<TfsSource TaskAction="GetChangeset"
Login="myDomain\someUser,password">
<Output TaskParameter="Changeset" PropertyName="ChangeSet" />
</TfsSource>
I think this has something to do with the workspace being missing - but Jenkins pulls everything down fine, so shouldn't the workspace exist?
Some guidance would be appreciated as I am starting to go bald over this.
Supporting Material:
Can you do a TFS get without needing a workspace?
Solution 1:
By-pass the TFS voodoo, get Git for TFS, and run the below.
(This would be the equivalent of "svn.exe 'export'" if you know that world.
"C:\MyProgFiles\GitTF\git-tf.cmd" clone http://MyCoolteamfoundationserver:8080/tfs/ $/MySolution/
Solution 2:
Create the workspace and map it and then "get" the code.
Here is a .bat version that you would mimic:
set __MYWORKSPACENAME=CI_TEMP_WORKSPACE
set __BASEDIRECTORYFINAL=c:\ci_build_stuff\
MD %__BASEDIRECTORYFINAL%
CD %__BASEDIRECTORYFINAL%
set __tfExe=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\TF.exe
"%__tfExe%" workspace /new %__MYWORKSPACENAME% /collection:http://my_super_cool_teamfoundationserver:8080/tfs/my_cool_projects /noprompt
"%__tfExe%" workfold /map $/MyTFSPath %__BASEDIRECTORYFINAL%\SXA
"%__tfExe%" get %__BASEDIRECTORYFINAL%\MyTFSPath\ /recursive /noprompt
set __BASEDIRECTORYFINAL=
set __MYWORKSPACENAME=
set __tfExe=
Further thoughts:
Checkout
http://msbuildextensionpack.codeplex.com/workitem/11709
That might have some built in workspace voodoo in it, that isn't there on the changeset.
Get the source code and look around, it'll tell you what's going on.
I see this one:
http://msbuildextensionpack.codeplex.com/SourceControl/latest#Solutions/Main/TFS/TeamBuild.cs
public class TeamBuild : BaseTask
{
private const string GetLatestTaskAction = "GetLatest";
private const string QueueTaskAction = "Queue";
private const string RelatedChangesetsTaskAction = "RelatedChangesets";
private const string RelatedWorkItemsTaskAction = "RelatedWorkItems";

Using TFS TF History to determine the latest changeset

I'm writing a script that will run a build only if there is a change in source code. I need to know whether there is a change since the build last ran. This used to work because the folder would not be deleted, so it was easy to determine whether there was a change, but now everything is deleted everytime the build is run. I thought about using the TFS TF history command to query the last changeset or the last two changesets, but have had issues parsing just the changeset number from the output. I also considered using the changeset command. Is there any command-line parameter that I can use to answer the question, has there been a change since either a date, or a changeset number?
To the latest changeset number without local workspace, please use this command:
tf history /collection:"http://server:8080/tfs/Collection" "$/Project" /recursive /stopafter:1 /noprompt /login:domain\user,password
excerpt from my batch file to build.
set _aPath="f:\TFS\a"
set _TFPath="c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"
...
pushd %_aPath%
%_TFPath%\TF.exe history . /r /noprompt /stopafter:1 /Version:W > temp
FOR /f "tokens=1" %%a in ('findstr /R "^[0-9][0-9]*" temp') do set _BuildVersion=10.3.0.%%a
del temp
popd
uses a temp file, but works well.
As Andrew mentioned, TFS has continuous integration functionality built-in. However, yes, it's easy to query the changesets since a certain point, be it a date or a changeset. You want to look at the history between that changeset and latest:
tf history <folder> /version:C<changeset>~T /noprompt /recursive
If the only line output is the changeset you queried for, then obviously there have been no changes since that checkin. Otherwise, you will see the additional changesets, one per line.
There is an adaptor that can integrate BuildForge and Microsoft Team Foundation Server. Here is the url if you are interested...http://www-304.ibm.com/partnerworld/gsd/solutiondetails.do?&solution=46360&lc=en
The Automatra TFS Adaptor for Rational Build Forge provides Continuous Integration (CI) and reporting capabilities.
The TFS Adaptor further enables CI capabilities at both the TFS Source (Change Set) and WorkItem levels. Out of the box reporting delivers clear Bill of Materials (BOM) reports that can be delivered to downstream consumer of your builds.
Finally, as you must be aware, the strength of Build Forge is its capability to bridge build with deployment (and beyond). Obviously, with these Continuous Integration capabilities you can then move forward with the continuous delivery capability I believe you wish to achieve.
My PowerShell script that is called GetVcsRevision.ps1 and located in subfolder of VCS Root:
param (
[string]$PathToTF='C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe'
,[Parameter(Mandatory=$true)][string]$Login
,[Parameter(Mandatory=$true)][string]$Password
)
$result = &$PathToTF #("history","/stopafter:1","/recursive","..\*","/login:""$Login"",""$Password""") 2>&1 3>&1
if ($result.GetType().Name -eq "Object[]")
{
<# $result format is:
Changeset User Date Comment
--------- ----------------- ---------- ----------------------------------------
26038 user 24.06.2014 Sample commit comment
$result[2] is:
26038 user 24.06.2014 Sample commit comment
$result[2].Split(" ")[0] is:
26038
#>
$result[2].Split(" ")[0]
}
else
{
"0"
}
It is sending last changeset number to out pipe. If something goes wrong, then this number is 0.
You can make a function from this script and call it in you build script.
My one-line command:
for /f "usebackq tokens=*" %%a in (`tf history . /recursive /noprompt /stopafter:1 /version:T ^| powershell -Command "$input | ? { $_ -imatch '^(\d+)\s+' } | %% { $matches[0].Trim() } | Select-Object -First 1"`) do set TIP_CHANGESET=%%a
after execution TIP_CHANGESET env. variable contains tip changeset

Resources