I am new to Powershell and I am writing a script to push a package to Octopus Deploy.
#Function to push packages to Octopus Deploy
function Push-Package {
param(
$OctopusUri,
$ApiKey,
$Package
)
try{
Write-Host "Pushing $($Package.Fullname) to Octopus"
.\Octo.exe 'push' --package $Package.Fullname --server $OctopusUri --apiKey $ApiKey --logLevel 'verbose'
Write-Host "Pushing $($Package.Fullname) to Octopus - Success"
}
catch{
Write-Host "PUSH PACKAGE Exception--------- $_"
}
}
$OctopusUri = "https://MyTestOctopus.local"
$ApiKey = "API-3Z3NRPNLUTS6ULA2KDALWG6A3HA"
$PackageFolder = "c:\temp\OctoTest"
Push-Package "https://MyTestOctopus.local" "API-3Z3NRPNLUTS6ULA2KDALWG6A3HA" "C:\temp\OctoTest\MyTestPackage.1.1.0.zip"
I am getting an error:
PUSH PACKAGE Exception--------- The term '.\Octo.exe' is not recognized as the name of a cmdlet, function, script file, or operable program
I am not sure what I am doing wrong above. Any help would be great.
Related
I have a powershell script A.ps1 as below:
param([switch] $p1, [switch] $p2)
if ($p1.IsPresent)
{
$p1 = 2
& $B -onboardingId "" -p1 $p1.IsPresent $message = "Deployment In Progress" -connectionString $connectionString
}
elseif ($p2.IsPresent)
{
$p2 = 3
& $B -onboardingId "" -p2 $p2.IsPresent $message = "Deployment In Progress" -connectionString $connectionString
}
The script A.ps1 is calling B.ps1 from itself. Both the scripts are placed in the same path. But I am getting the error below when I try to call script:
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object.
I tried -ArgumentList but it did not work out for me.
I tried to resolve the issue by referring online but I was not able to resolve it. Can I please get help on this?
Thank you.
In my Pester-test I've created a function to Test-SQLConnection.
I can test the function like this:
param(
[string]
$Server,
[string]
$Database
)
BeforeAll {
$testDbServer = $Server
$testDatabase = $Database
}
Describe "Status Databaseserver" {
It "Should login with integrated security" {
Test-SQLConnection "Data Source=$testDbServer; Database=$testDatabase;Integrated
Security=True"; | Should -BeTrue
}
}
function Test-SQLConnection
{
[OutputType([bool])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$ConnectionString
)
try
{
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $ConnectionString;
$sqlConnection.Open();
$sqlConnection.Close();
return $true;
}
catch
{
return $false;
}
}
This approach works when I run the test locally on my machine. But when I test from Azure release pipeline I get this error:
CommandNotFoundException: The term 'Test-SQLConnection' is not recognized as the name of a cmdlet, function, script file, or operable program.
What am I doing wrong here?
Per the comments, your function needs to be in the BeforeAll block because with Pester v5 and newer Pester now performs a "discovery" phase before executing your tests:
All code should now be put into It, BeforeAll, BeforeEach, AfterAll,
or AfterEach. Put no code directly into Describe, Context or on the
top of your file without wrapping it in one of these blocks (unless
for good reason).
If code is not put in the proper place, it will run in Discovery, and
the results will not be available during Run. During the Run phase,
the internal tree of containers, blocks, and tests are run.
-- https://www.sapien.com/blog/2021/01/20/migrating-from-pester-4-to-pester-5/
I suspect what was occurring for you is that your local machine has an older version of Pester, but when run on Azure DevOps its using the latest.
I have a script to push a package to Octopus which works. I want to push the package a number of times say 10. But to do this I need to increment the package number by 1 each time. I cant upload the same package number twice. The pushing to Octopus works but im not sure where to start with the increment of the package from MyTestPackage.1.1.0.zip to MyTestPackage.1.1.1.zip. The 0 at before the .zip will need to increment by 1 each time.
I was think of a for loop to upload package 10 times?? Any help would be great
function PushPackage {
param(
$OctopusUri,
$ApiKey,
$Package
)
try{
Write-Host "Pushing $Package to Octopus"
Start-Process -NoNewWindow -FilePath $OctopusExePath
& $OctopusExePath push --package $Package --server $OctopusUri --apiKey $ApiKey --logLevel 'verbose'
Write-Host "Pushing $Package to Octopus - Success"
}
catch{
Write-Host "PUSH PACKAGE Exception--------- $_"
}
}
$OctopusUri = "https://MyOctopusTest.local"
$ApiKey = "API-CRW9JBMJGUTEUEYEYUE"
$Package = "C:\temp\OctoTest1\MyTestPackage.1.1.0.zip"
PushPackage $OctopusUri $ApiKey $Package
I am trying to create a TeamCity build configuration for creating a Docker Image.
For redundancy, I want the first Build Step to check whether Docker is running on the TeamCity server, and start it if necessary.
I have created the following PowerShell script that does exactly that. The script even waits until Docker is fully functional before finishing.
# This File checks if docker is running, and starts it if necessary, waiting until it has finished starting up before exiting
# ---------
# VARIABLES
# ---------
$TimeoutInterval = 10 #Timeout interval for checking whether docker has finished starting, in seconds
$DockerPath = "C:\Program Files\Docker\Docker\Docker for Windows.exe"
# ---------
# FUNCTIONS
# ---------
Function ProcessRunning([string] $ProcessName) {
[bool] $Return = $False
if ( Get-Process | Where-Object {$_.Name -like $ProcessName} ) {
$Return = $True
}
Return $Return
}
# -------
# PROGRAM
# -------
# Enables Error Action Preference to stop to enable try-catches
$ErrorActionPreference = 'Stop'
if(ProcessRunning("Docker for Windows")){
echo "Docker is running"
echo ""
docker version
}else{
echo "Docker is not running"
echo ""
echo "Starting Docker"
echo ""
Start-Process $DockerPath
#Waits while Docker has not finished starting up
$dockerStarting = $true
while($dockerStarting){
try{
docker version
$dockerStarting = $false
}catch{
echo ""
echo "Docker is still starting up..."
echo ""
$dockerStarting = $true
Wait-Event -Timeout $TimeoutInterval
}
}
echo ""
echo "Docker has finished starting up!"
echo ""
}
This script works fine when executed locally on the TeamCity server. However, when I attempt to run it as a BuildStep, it appears to ignore the try-catch block like it did in my local version before I set the $ErrorActionPreference = 'Stop'
Specifically, the docker version command fails as I intended it to to indicate that Docker is not yet fully running. However, the try-catch block fails to catch it as it does when run locally on the server.
I have already tried both values of Format stderr output as: as well as Script execution mode:, but the result remains the same: The script throws an error, and Docker is not started on the TeamCity Server.
Now, my basic question is: Is what I'm trying even technically possible? Because I could imagine that TeamCity employs some sort of safeguard mechanism that prevents certain changes on the Server it's run from. Then again, I have in the past successfully employed PowerShell scripts to copy and delete files on the Server, so honestly, at this point I'm more confused than anything about why this doesn't seem to work.
Any input on this would be greatly appreciated.
Okay, so I tried around a lot, and eventually found a solution that allows me to check if Docker is running via a TeamCity build step and successfully start it if not.
This actually turned out to be a two-tier problem, with two separate things having to be done in order to make it work:
1.) Run the TeamCity Build Agent Service as an elevated local account
In my case, I had the TeamCity Build Agent Service running under the SYSTEM account. I switched it to an Administrator account using:
Services
↳TeamCity Build Agent
↳Log On>Log on as
↳◉This account: .\Administrator
2.) Use a "clean" skript that does not rely on try-catch to see if Docker is running
The final PowerShell Skript that I'm using now and that works nicely looks like this:
# This File checks if docker is running, and starts it if necessary, waiting until it has finished starting up before exiting
# ---------
# VARIABLES
# ---------
$TimeoutInterval = 10 #Timeout interval for checking whether docker has finished starting, in seconds
$DockerPath = "C:\Program Files\Docker\Docker\Docker for Windows.exe"
# ---------
# FUNCTIONS
# ---------
Function ProcessRunning([string] $ProcessName) {
[bool] $Return = $False
if ( Get-Process | Where-Object {$_.Name -like $ProcessName} ) {
$Return = $True
}
Return $Return
}
# Determines if a Service exists with a name as defined in $ServiceName.
Function ServiceExists([string] $ServiceName) {
[bool] $Return = $False
if ( Get-Service "$ServiceName*" -Include $ServiceName ) {
$Return = $True
}
Return $Return
}
# Determines if a Service with a name as defined in $ServiceName exists and is running
Function ServiceRunning([string] $ServiceName) {
[bool] $Return = $False
Write-Host "Checking if Service "$ServiceName" exists and is running"
Write-Host ""
if ( Get-Service "$ServiceName*" -Include $ServiceName ) {
$arrService = Get-Service -Include $ServiceName
if ( $arrService.Status -eq "Running" ) {
Write-Host "Service "$ServiceName" exists, and is running!"
Write-Host ""
$Return = $True
}else{
Write-Host "Service "$ServiceName" exists, but is not running!"
Write-Host ""
}
}else{
Write-Host "Service "$ServiceName" does not exist!"
Write-Host ""
}
Return $Return
}
# -------
# PROGRAM
# -------
if(ProcessRunning("Docker for Windows")){
Write-Host "Docker is running"
Write-Host ""
docker version
}else{
Write-Host "Docker is not running"
Write-Host ""
Write-Host "Starting Docker"
Write-Host ""
Start-Process $DockerPath
#Waits while Docker has not finished starting up
$dockerStarting = $true
while($dockerStarting){
if((ServiceRunning("com.docker.service")) -and (ServiceRunning("docker"))){
Write-Host ""
Write-Host "Docker has finished starting up!"
Write-Host ""
docker version
$dockerStarting = $false
}else{
Write-Host ""
Write-Host "Docker is still starting up..."
Write-Host ""
#Attempts to start the relevant services
if(!(ServiceRunning("com.docker.service"))){
if(ServiceExists("com.docker.service")){
Start-Service "com.docker.service"
}
}
if(!(ServiceRunning("docker"))){
if(ServiceExists("docker")){
Start-Service "docker"
}
}
$dockerStarting = $true
Wait-Event -Timeout $TimeoutInterval
}
}
}
I still have no idea why try-catch isn't working in TeamCity, so if someone knows the answer to that, please comment.
Anyway, I hope this solution is helpful to someone.
I have put together a PSake (v2.0) build script, and the script is setting the $psake.build_success property as true even thought the call to MSBuild fails. Can anyone advise me on how to alter the script so that the $psake.build_success property will correctly return false when the MSBuild call fails?
My PSake build script is as follows:
properties {
$solutionFile = 'SOLUTION_FILE'
$buildSuccessfulMessage = 'Solution Successfully Built!'
$buildFailureMessage = 'Solution Failed to Build!'
$cleanMessage = 'Executed Clean!'
}
task default -depends BuildSolution
task BuildSolution
{
msbuild $solutionFile /t:Clean,Build
if ($psake.build_success)
{
$buildSuccessfulMessage
}
else
{
$buildFailureMessage
}
}
Is PowerShell's native $lastExitCode (i.e., WIn32 ExitCode) any use in the context? I'd be guessing that the built in one is only relevant when you're invoking a psake-related cmdlet.
i.e., replace the check with
if($lastexitcode -eq 0) {
Disclaimer: Only podcast level experience with psake :D
The issue seems to be that the call to MSBuild operation actually completes successfully, whilst the build operation it initiates fails. The way I was able to get around this was to pipe the output of the MSBuild call to a text file, and then parse the file for the string "Build Failed". If it contained the string, obviously the build failed.
My PSake build script is as follows:
properties {
$solutionFile = 'SOLUTION_FILE'
$buildSuccessfulMessage = 'Solution Successfully Built!'
$buildFailureMessage = 'Solution Failed to Build!'
$cleanMessage = 'Executed Clean!'
}
task default -depends Build
task Build -depends Clean {
msbuild $solutionFile /t:Build /p:Configuration=Release >"MSBuildOutput.txt"
}
task Clean {
msbuild $solutionFile /t:Clean
}
and in my calling script:
function Check-BuildSuccess()
{
return (! (Find-StringInTextFile -filePath .\MSBuildOutput.txt -searchTerm "Build Failed"))
}
function Is-StringInTextFile
(
[string]$filePath = $(Throw "File Path Required!"),
[string]$searchTerm = $(Throw "Search Term Required!")
)
{
$fileContent = Get-Content $filePath
return ($fileContent -match $searchTerm)
}
There is the psake Exec command that you can wrap msbuild with and a powershell error is thrown.
Exec {
msbuild $solutionFile "/p:Configuration=$buildConfiguration;Platform=$buildPlatform;OutDir=$tempOutputDirectory"
}
Neither $LastExitCode or $_ worked for me. This did however:
$buildArgs = "MySolution.sln", "/t:Build", "/p:Configuration=Debug"
$procExitCode = 0
$process = Start-Process -FilePath "msbuild" -ArgumentList $buildArgs -NoNewWindow -PassThru
Wait-Process -InputObject $process
$procExitCode = $process.ExitCode
#aha! msbuild sets the process exit code but powershell doesn't notice
if ($procExitCode -ne 0)
{
throw "msbuild failed with exit code $procExitCode."
}
P.S. If you use this in production I recommend adding -timeout handling to Wait-Process