TFS Build variable current sprint TFS 2015 - tfs-2015

We have a CI build server doing automated builds and would like to include the current sprint/iteration number in the assembly version. Is there an environment variable or easy way of getting the current sprint number in the build processes? TFS On Permise 2015 Update 3

There isn’t build-in variable to get current sprint, but you can use REST API.
Steps:
Add a PowerShell file to the source control (e.g. included in your project and check in)
Code:
Param(
[string]$collection,
[string]$projectName,
[string]$token
)
$uri="$collection/$projectName/_apis/work/teamsettings/iterations?`$timeframe=current&api-version=v2.0-preview"
Write-Output $uri
$result = Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization=("Bearer {0}" -f $token)}
Write-Output "success"
Write-Output $result.value.path
Write-Host "##vso[task.setvariable variable=currentSprint;]$($result.value.path)"
Edit your build definition
Click Options tab and check Allow Scripts to Access OAuth Token
Add PowerShell build step and specify PowerShell file (step 1) (arguments: -collection $(System.TeamFoundationCollectionUri) -projectName $(System.TeamProject) -token $(System.AccessToken) )
After that, the current sprint value is stored in currentSprint variable.

Related

Create keyvault secret - Operation returned an invalid status code 'Conflict'

I want to create multiple secrets in keyvault. Assign dynamic values of Blobstorage account, Batch account.
I tried below code to create secrets:
Function CreateKeyvaultSecrets
{
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string] $keyvaultName,
[Parameter(Mandatory=$true, Position=1)]
[string] $blobStorageAccountName,
[Parameter(Mandatory=$true, Position=2)]
[string] $batchaccountName,
[Parameter(Mandatory=$true, Position=3)]
[string] $logRgName
)
#Get Storagekey
$blobStorageKeyObject = (Get-AzStorageAccountKey -ResourceGroupName $logRgName -AccountName $blobStorageAccountName)| Where-Object {$_.KeyName -eq "key1"}
$blobStorageKey = $blobStorageKeyObject.Value
$blobStorageConnectionString = "DefaultEndpointsProtocol=https;AccountName=$blobStorageAccountName;AccountKey=$blobStorageKey;EndpointSuffix=core.windows.net"
#Create blobstorage key secret
$blobSecretkey = ConvertTo-SecureString -String $blobStorageKey -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName $keyvaultName -Name 'blobstorageaccesskey' -SecretValue $blobSecretkey
#Create blobstorage connectionstring key secret
$blobconnectionstringSecret = ConvertTo-SecureString -String $blobStorageConnectionString -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName $keyvaultName -Name 'blobstorageconnectionstring' -SecretValue $blobconnectionstringSecret
Write-host "Blob Storage Account connection string added to Keyvault secret"
}
CreateKeyvaultSecrets 'kvtevalmock' 'steval' 'abtaeval' 'rg-eval'
I am trying to execute above code from Azure DevOps Powershell task. Azure powershell version is 5.
Secrets are not getting creating. Below error is thrown:
WARNING: Upcoming breaking changes in the cmdlet 'Set-AzKeyVaultSecret' :
- The output type 'Microsoft.Azure.Commands.KeyVault.Models.PSKeyVaultSecret' is changing
- The following properties in the output type are being deprecated : 'SecretValueText'
- The change is expected to take effect from the version : '3.0.0'
Note : Go to https://aka.ms/azps-changewarnings for steps to suppress this breaking change warning, and other
information on breaking changes in Azure PowerShell.
##[error]Operation returned an invalid status code 'Conflict'
##[error]PowerShell exited with code '1'.
I test your script on my side, it works fine.
From the error message, looks your Az.KeyVault powershell module version is too old, my version is 3.4.0, try to update it with the command below.
Update-Module -Name Az.KeyVault -Force
After the update, close all the powershell sessions and open a new one to try again, it should work.

AutoIncrementing Build with Core and DevOps Pipeline

I'm trying to setup an auto-incrementing version number for my ASP.NET Core 3.1 web app built using Azure Pipelines. I've tried various snippets and pipeline tasks and got as far as generating the version number but my build fails with the message
The specified version string does not conform to the required format - major[.minor[.build[.revision]
I'm using the below snippet of yml to generate the version number:
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
version.MajorMinor: '1' # Manually adjust the version number as needed for semantic versioning. Revision is auto-incremented.
version.Revision: $[counter(variables['version.MajorMinor'], 0)]
versionNumber: '$(version.MajorMinor).$(version.Revision)'
steps:
- task: PowerShell#2
displayName: Set the name of the build (i.e. the Build.BuildNumber)
inputs:
targetType: 'inline'
script: |
$doy = (Get-Date).DayofYear
Write-Host "##vso[task.setvariable variable=DayOfYear]$doy"
$rev = $env:BUILD_BUILDNUMBER.Split('.')[-1]
Write-Host "##vso[task.setvariable variable=Revision]$rev
Write-Host "set Revision to $rev"
[string] $buildName = "$(versionNumber).$doy.$rev"
Write-Host "Setting the name of the build to '$buildName'."
Write-Host "##vso[build.updatebuildnumber]$buildName"
This does generate a version number (1.26.199.50), however when I get the the MSBuild task:
task: VSBuild#1
inputs:
solution: '$(solution)'
msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site" /p:Version=$(buildName)'
I get the version error. I've even tried replacing the version with 1.0.199.50 but I get the same error. I understand that each segment has to be less than 65534 as that's the max value for a UInt so I don't understand why it's failing.
After much frustration, I did this with a Powershell script in the release pipeline instead. I've got a Powershell task containing the below which is before the File Transform task. Steps to get it working.
Add a release pipeline variable called "MajorVersion". This is the first part of the version string
Add a property to appsettings.json called AppConfig.Version, set it to whetever for local testing.
Add a powershell task. The order should be Powershell Task->File Transform->App Service Deploy:
$doy = $(Get-Date).DayofYear
[string] $buildName = "$Env:MajorVersion.$doy.$Env:BUILD_BUILDNUMBER"
Write-Host "##vso[task.setvariable variable=AppConfig.Version;]$buildName"
Access the variable from your app settings using your preferred method. In core, probably via Configuration.GetSection("blah")
The assembly isn't stamped with the version, but you can get to it to display on the UI. I feel like this needs to be simplified by MS as auto-incrementing a version shouldn't be so difficult.

Running SQL against multiple DB in azure pipeline

I want to set up the step in release process for azure pipeline where I can run the SQL from the file checked into the repo against multiple databases.
In my environment, I have one central db, one of the table for e.g "Control" table, keeps the connection to all the databases against which I need to run the sql during the deployment.
What I dont want to do is to setup the deployment step for each database. Is Powershell my only friend?
If so, how can I let powershell know what is the SQL in the file checked in during the deployment?
What I dont want to do is to setup the deployment step for each database. Is Powershell my only friend? If so, how can I let powershell know what is the SQL in the file checked in during the deployment?
In your case, Powershell seems to be the most appropriate.
In order to get the SQL in the file checked in during the deployment, we could use the powershell scripts to get the file names and paths, like:
$files=$(git diff HEAD HEAD~ --name-only)
$temp=$files -split ' '
$count=$temp.Length
echo "Total changed $count files"
For ($i=0; $i -lt $temp.Length; $i++)
{
$name=$temp[$i]
echo "this is $name file"
Copy-Item "$name" -Destination "$(System.DefaultWorkingDirectory)\SQLDeploymentFolder"
}
Check the ticket for some more details.
Then, we could use the extension Run SQL Server Scripts or Run SQL / SQLCMD Scripts passing multiple SQLCMD variables to all SQL Scripts in a folder.
Hope this helps.

Azure Pipeline - Increment build number and display in web app

I have the following simple build pipeline working in Azure DevOps with releases deployed to a staging slot.
I would like to have a build revision/version string and that is auto-incremented. I then want to display this in my web app so I can tell which version of the software is in production.
Currently I display the version string from the .csproj file. Something like this in a
<Version>1.1.4.7</Version>
And then displayed on a web page using the following code:
Version: #typeof(Startup).Assembly.GetName().Version.ToString()
If I can update the existing version string that would be great but I'm open to changing to whatever's easiest to integrate in the CI process.
Versioning has been simplified in the .Net Core world.
Edit your csproj and modify it as follows:
<PropertyGroup>
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">1.0.0.0</Version>
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>
If your file doesn’t have a version node, add the above.
The above setup will mean debugging locally will give you a version of 1.0.0.0, and in the event, you build in a non-Azure DevOps environment you will also end up with a 1.0.0.0 version. $(BUILD_BUILDNUMBER) is an environment variable set by Team Build and which will be updated at build time by VSTS or TFS.
The .Net version needs to be in the format [major].[minor].[build].[revision] with each segment being a number between 0 and 65000. You can configure the build number format in the Options tab, see here more info about the formatting. See here for helpful steps on configuring the build.
I am using ADO pipeline variables and the counter function like this
The patch variable is $[counter(format('{0}.{1}',variables['Major'], variables['Minor']),0)]
Then I put all of these values directly into a variable as a powershell task.
- task: InlinePowershell#1
displayName: Create Version Number
inputs:
Script: |
param($major, $minor, $patch)
$bv = "$major.$minor.$patch"
Write-Host "##vso[task.setvariable variable=buildVersion]$bv"
Write-Host "Version of net App : $bv"
ScriptArguments: '-major $(Major) -minor $(Minor) -patch $(Patch)'
Now when I do the .net publish I just pass the version
- task: DotNetCoreCLI#2
displayName: Publish Application
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/MyAPIProject.csproj'
arguments: '-r $(buildPlatform) -o $(Build.BinariesDirectory) -c $(buildConfiguration) --self-contained true /p:Version=$(buildVersion)'
zipAfterPublish: false
modifyOutputPath: false
What is really nice about this, is the patch gets seeded at zero, then every follow up build will auto-increment.
You should Use Azure DevOps Pipelines Release (a.k.a. Azure Pipelines release) instead of Azure DevOps Pipelines build (a.k.a. Azure Pipelines build). Azure Pipelines release by default will auto-increment your releases.
Azure Pipelines build has no automatic version numbering by default. Because increasing version after it should be done at release stage, because build should only concerns the continuous integrations, not to be used as versioning a build to be released.
This is the official docs of Azure Pipelines release on auto-increment your release:
https://learn.microsoft.com/en-us/azure/devops/pipelines/release/?view=vsts#numbering
In a .NET Core (.NET 6.0 in particular) app I have set the following code in .csproj:
<PropertyGroup>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</PropertyGroup>
Then in Azure DevOps I have added the following powershell script task to set version on my build.
Note that I am using the below convention:
Major -> Phase/Product cycle. I am using a variable/parameter to pass this value in the pipeline.
Minor -> Sprint number. I am using a variable/parameter to pass this value in the pipeline.
Revision -> Max limit for this number is 65000 and therefore cannot use Build.BuildNumber. I am using (Date:YY)(DayOfYear).
Build -> Taking the second part of the Build.BuildNumber (increment of the day)
- task: PowerShell#2
displayName: 'Edit AssemblyInfo'
inputs:
targetType: 'inline'
script: |
$Major = "$(Major)"
Write-Host "Major: $Major"
$Minor = "$(Minor)"
Write-Host "Minor: $Minor"
$DayOfYear = (Get-Date).DayOfYear
$Year = (Get-Date –format yy)
$Revision = '' + $Year + $DayOfYear
Write-Host "Revision: $Revision"
$BuildNumber = "$(Build.BuildNumber)"
Write-Host "BuildNumber: $BuildNumber"
$Build = $BuildNumber.Split('.')[1]
Write-Host "Build: $Build"
$pattern = '<AssemblyVersion>(.*)</AssemblyVersion>'
Write-Host "Will search in paths.."
$csProjFiles = Get-ChildItem .\*.csproj -Recurse
Write-Host "CsProjFiles found are: "
Write-Host "$csProjFiles"
foreach ($file in $csProjFiles)
{
(Get-Content $file.PSPath) | ForEach-Object{
if($_ -match $pattern){
# We have found the matching line
# Edit the version number and put back.
Write-Host "Matched $file"
$fileVersion = [version]$matches[1]
$newVersion = "{0}.{1}.{2}.{3}" -f $Major, $Minor, $Revision, $Build
'<AssemblyVersion>{0}</AssemblyVersion>' -f $newVersion
} else {
# Output line as is
$_
}
} | Set-Content $file.PSPath
}

What's in teamcity custom_script.cmd

I'm trying to dig into the depths of teamcity to get a better understanding of what its doing under the hood(and improve my own build knowledge). I noticed that when I run a build step it then executes its own .cmd which I presume wraps up the msbuild scripts. The problem is that whenever I look in the directory specified the file doesn't exist as I'm guessing it creates, executes then deletes almost instantly. Any suggestions on how to access the file? or what's inside?
Starting:D:\TeamCity\buildAgent\temp\agentTmp\custom_script5990675507156014131.cmd
A temporary file is created by TeamCity when you run add a Command Line Build Step with "Custom script" as runner.
The content of this file would be the Custom script you specified inside the user interface.
The produced output would be:
Step 1/1: Command Line (1s)
Starting: D:\TeamCity\buildAgent\temp\agentTmp\custom_script2362934300799611461.cmd
in directory: D:\TeamCity\buildAgent\work\c72dca7a7355b5de
Hello World
Process exited with code 0
In case anyone is wondering about this still, you can force echo back on.
Put as the first thing in the custom script
#echo on
this will undo the silent commands teamcity defaults to.
I looked around for a while but there seems to be no configuration variable in TeamCity allowing to keep generated files. Now if the commands executed take some time, e.g. more than a couple of seconds, you could just open the temp directory in explorer and start hitting F5 (refresh) from the moment a build is started until you see the .cmd file appear, then be quick and right-click it and select 'Edit' to open it in a text editor. If that is too hard you can try with the solution presented here: create a Powershell script with code like this:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "D:\TeamCity\buildAgent\temp\agentTmp"
$watcher.Filter = "*.cmd"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
$action = { $path = $Event.SourceEventArgs.FullPath
Add-content "D:\log.txt" -value (Get-Content $path)
}
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
while ($true) {sleep 1}
and run it. When the build starts and creates a cmd file, the powershell script will copy the content to d:\log.txt. This will still not work for very short-lived scripts though. In that case I'd just make the script last longer by adding something like
ping 127.0.0.1 -n 5 -w 1000 > NUL
which will make it last at least 5 seconds.