I am adding a project into teamcity and need to add a powershell script to change some config settings and generate a zipped artifact. I have built and tested the script file outside of teamcity but in order to make it work during the build I need to get the path where the artifact is built to.
Is there a way to replace in the code below the c:\artifacts\myproject\build\38 with a teamcity parameter which will always pick up the latest build directory?
#Find and replace various app.config settings
$location = C:\Artifacts\MyProject\Build\38\myApp\myConfig.config";
(Get-Content $location) |
ForEach-Object { $_ -replace '<add key="platform" value="xxxx"/>', '<add key="platform" value="test"/>' } |
Set-Content $location
#Should take source directory and create a zip file from it
$source = "C:\Artifacts\MyProject\Build\38\myApp\"
$destination = "C:\Artifacts\FrontOfficeApi\Build\38\artifact.zip"
GenerateZipFile -DestinationFilePath $destination -SourcePath $source
Many thanks
$buildDirectory = "%teamcity.build.checkoutDir%" Will give you the directory where the source code has been checked out to, so you can work relatively from there. This is if you are running the PowerShell as source code, otherwise you can pass parameters into a PowerShell script using the same variable.
Hope this helps
Related
I've created an active directory account creation script using powershell 4.
My Boss has stated there's a new policy where we have to build a login script per user, is there a way to do this where it'll build the .bat file and map the drives that we specify within the script?
I know there's a way to build .txt files, but not sure about .bat.
What I need
Select Drives That The user Needs Access To
I need it to build a .bat file, mapping the drives previously specified.
Then move it to the login script folder on the DC, mapped to S
For Future reference to anybody who wants to do this.
I've managed to resolve it myself after some playing around.
$NewName = $SAMAccountName
$extension = ".bat"
$FileName = "$SAMAccountName$extension"
$ScriptDrive = "\\IPREMOVED\scripts"
Write-Output "
BAT CONTENTS" `n`n|FT -AutoSize >>LoginScript.txt
Get-ChildItem LoginScript.txt | Rename-Item -NewName $FileName
Move-Item -Path ".\$FileName" -Destination $ScriptDrive
I am really new to the Powershell and want to copy a file from BUILD_SOURCESDIRECTORY environment variable to a zip folder inside BUILD_STAGINGDIRECTORY environment variable in my VSTS build definition.
if(Test-Path $Env:BUILD_SOURCESDIRECTORY/MyFolder/MyFIle.txt)
{
Write-Host "Source File: $Env:BUILD_SOURCESDIRECTORY/MyFolder/MyFIle.txt"
Write-Host "Target Location: $Env:BUILD_STAGINGDIRECTORY\StagingDirectoryFolder.zip\TestFolder"
}
Copy file from one path to another is quite straight forward but I really don't know how to move file into the zip folder structure.
If I could suggest a non power shell solution (although it is worth looking up the Expand-Archive and Compress-Archive cmdlets as recommended in the comments.)
I would use a Archive Files build task to handle the zipping. In your power shell build script, copy your artifact(s) into $ENV:BUILD_BINARIESDIRECTORY, and then leverage the VSTS build to do the archiving of all of the files.
This then lets you publish that zip file using the VSTS build which will allow it to be easily accessible through the VSTS web gui which imo offers a superior user experience (for troubleshooting your build, as well as other users who need access to those artifacts (either physical people, or automated processes)). If you need to do something else with the zip file, you could then add another powershell script after your archive files that would be able to access the file from the $ENV:BUILD_ARTIFACTSTAGINGDIRECTORY. This way your scripts stay simple, and you can offload some of your build maintenance onto Microsoft.
You can copy MyFIle.txt to the subfolder TestFolder under a zip file by Expand-Archive and Compress-Archive (as gvee mentions). The PowerShell script as below:
if(Test-Path $(Build.SourcesDirectory)\MyFolder/MyFIle.txt)
{
clear-host
[string]$zipF = '$(Build.ArtifactStagingDirectory)\StagingDirectoryFolder.zip'
[string]$fileToZip = '$(Build.SourcesDirectory)\MyFolder\MyFIle.txt'
[string]$tempEx= '$(Build.SourcesDirectory)\temp'
[string]$copyDes='$(Build.SourcesDirectory)\temp\TestFolder'
Expand-Archive -Path $zipF -DestinationPath $tempEx -Force
Copy-Item $fileToZip -Destination $copyDes -Force
Compress-Archive -Path $tempEx\* -Update -DestinationPath $zipF
Remove-Item -Recurse -Force $tempEx
}
Now the zip file $(Build.ArtifactStagingDirectory)\StagingDirectoryFolder.zip contains MyFIle.txt under $(Build.ArtifactStagingDirectory)\StagingDirectoryFolder.zip\TestFolder.
I have done some searching on this topic and am able to find individual solutions to generate custom build numbers as well as patch assembly info, however I am unable to accomplish both. When using a custom POWERSHELL script that I found in a search, I am able to set the build number to what I create with the script, however this build number does not patch. The only success I have in patching is when using set numbers plus a counter. But the number that the POWERSHELL script creates does not persist to an extent that the Assembly patcher can work with. Am I doing it wrong?
In our project, we solved it using a the CommonAssemblyInfo.cs file. Basically add it to your solution, remove the AssemblyInfo.cs files from the individual files and when you compile all dlls will have the assembly info that is specified in the CommonAssemblyInfo.cs file.
We update this file as the first step before we do the compiling. The unique number we use is the changeset id from the source control system (in our case TFS). Basically, the source control change set number is guranteed to be unique and highly relevant. It will tell you exactly which assembly was generated by which changeset in your source control.
Basically the first step in our build configuration is a powershell script that looks something like below (Update path to CommonAssemblyInfo.cs accordingly)
$fileLocation = Join-Path -Path "%teamcity.build.checkoutDir%" -ChildPath "Source\CommonAssemblyInfo.cs"
$oldValue = "AssemblyVersion\(""(\d+)\.\d+\.\d+\.\d+""\)"
$newValue = 'AssemblyVersion("$1.0.0.%build.vcs.number%")'
(get-content $fileLocation) | foreach-object {$_ -replace $oldValue, $newValue} | set-content $fileLocation
So build setp 1, update your assembly version with the Changeset number as above. Step 2, compile your solution. Step 3 to x, Test, Deploy etc. etc.
I finally solved it with a little bit of Chaitanya's provided logic... but modified:
$ww = ([Math]::Floor([DateTime]::Now.DayOfYear/7)+1)
Write-Host "##teamcity[buildNumber '%major.minor%.$ww.%build.counter%']"
$fileLocation = Join-Path -Path "%teamcity.build.checkoutDir%" -ChildPath "\SourceDir\AssemblyInfo.cs"
$oldValue = "AssemblyFileVersion\(""(\d+)\.\d+\.\d+\.\d+""\)"
$newValue = [string]::Concat("AssemblyFileVersion(""%major.minor%.", $ww, ".%build.counter%", """)")
(get-content $fileLocation) | foreach-object {$_ -replace $oldValue, $newValue} | set-content $fileLocation
I have created a PowerShell script for copying files to a directory, the script, first creates a folder , or forces a new folder event if it exists. Then copies a directory from another location. After copying, the files I then need to copy the correct web config depending on a value given by the user execturing the script. The issue I am having is I can copy the files, but all the files are set to read-only meaning when I try and copy the correct web.config, the script fails as access is denied.
This is a cut down version of script for simplicity.
$WebApp_Root = 'C:\Documents and Settings\user\Desktop\Dummy.Website'
$Preview_WebApp_Root = 'c:\applications\Preview\'
$Choice = read-host("enter 'preview' to deploy to preview, enter Dummy to deploy to Dummy, or enter test to deploy to the test environment")
if (($Choice -eq 'Preview') -or ($Choice -eq 'preview'))
{
$Choice = 'Preview'
$Final_WebApp_Root = $Preview_WebApp_Root
}
write-host("Releasing Build to " + $Choice +'...')
write-host("Emptying web folders or creating them if they don't exist... ")
New-Item $Final_WebApp_Root -type directory -force
write-host("Copying Files... ")
Copy-Item $WebApp_Root $Final_WebApp_Root -recurse
write-host("Copy the correct config file over the top of the dev web config...")
Copy-Item $Final_WebApp_Root\Config\$Choice\Web.configX $Final_WebApp_Root\web.config
write-host("Copying correct nhibernate config over")
Copy-Item $Final_WebApp_Root\Config\$Choice\NHibernate.config $Final_WebApp_Root\NHibernate.config
write-host("Deployed full application to environment")
Try to use -Force parameter to replace read-only files. From documentation:
PS> help Copy-Item -Par force
-Force [<SwitchParameter>]
Allows the cmdlet to copy items that cannot otherwise be changed,
such as copying over a read-only file or alias.
I was asked to write a PowerShell script that they can package in with their build updates. They will complete a build that gets dropped to a folder (say \server\build\release1.1.2). We need a script that takes all the files/folders from that folder and copies them to the appropriately named locations.
I need the script to also read the # of the current build from the folder title and create that same # build folder when it copies. Easy enough to that however I need the references to be all dynamic, so when that Release1.1.3 comes out wecan drop the same script into there and it will copy all the files to the appropriate directories (and create them if they don't exist).
This script should get you started. Run it to see an example of the values it produces.
# variable name chosen based on the automatic variable available to PowerShell Modules
$PSScriptRoot = ($MyInvocation.MyCommand.Path | Split-Path | Resolve-Path).ProviderPath
$BuildName = $PSScriptRoot | Split-Path -Leaf
#"
This script file is located at:
$($MyInvocation.MyCommand.Path)
The folder this script file is in is:
$PSScriptRoot
The name of the folder this script file is in is:
$BuildName
To copy files you might do this:
Copy-Item -Path `$PSScriptRoot\* -Destination C:\Install\`$BuildName -Recurse
"#