I've made a useful PowerShell script to automate our code deployments to Salesforce. After a couple of afternoons learning PS and some try/error, I finished my script and it's working.
Nonetheless, since it's my first long PS script I was hoping you guys could tip me in how I could do things better, make the script more readable, etc. I'm used to OOP, but this is a whole different story from what I've seen lol
Just as a quick introduction, what the code does is:
Validates that the repository I want to deploy to a Salesforce org has a package.xml (a file which enumerates what I'm going to deploy, like a check list)
Authenticates against Salesforce
Deploys all the repository and polls the server to update the status in the console
Runs the test and keeps polling to update the visual status
Reacts to deployment/test errors by printing them on the console
In order to achieve this I used the sfdx CLI which Salesforce provides, so it did save me a LOT of time.
param([string] $repositoryDirectory, [bool] $isProduction)
Write-Host -ForegroundColor green ":: Validating Repository ::"
$srcDirectory = [System.IO.Path]::Combine($repositoryDirectory, "src")
if(![System.IO.File]::Exists([System.IO.Path]::Combine($srcDirectory,"package.xml"))) {
Write-Host -ForegroundColor red "ERROR: package.xml not found in the ./src directory."
exit
}
Write-Host -ForegroundColor green "`n:: Authenticating to Salesforce ::"
if($isProduction) {
sfdx force:auth:web:login -s -r "https://login.salesforce.com"
}
else {
sfdx force:auth:web:login -s -r "https://test.salesforce.com"
}
Write-Host -ForegroundColor green "`n:: Deploying source code ::"
$deployJob = sfdx force:mdapi:deploy -d $srcDirectory -l "RunLocalTests" --json | ConvertFrom-Json
$deployJobId = $deployJob.result.id
$startedTests = $false
do {
$report = sfdx force:mdapi:deploy:report -i $deployJobId --json --verbose 2>&1 | ConvertFrom-Json
if($null -eq $report) {
continue
}
# Deployment progress block.
if($report.result.numberComponentsTotal -ne 0 -and $componentsRemaining -ne 0) {
$deploymentRatio = [Math]::Ceiling(100 * ($report.result.numberComponentsDeployed / $report.result.numberComponentsTotal))
$componentsRemaining = $report.result.numberComponentsTotal - $report.result.numberComponentsDeployed - $report.result.numberComponentsFailed
# If the percentage is not yet 100%, update it.
if($deploymentRatio -le 100) {
Write-Host -NoNewLine "`rComponents deployed: " $deploymentRatio "%"
}
# If the deployment has failed
if($report.result.status -eq "Failed") {
break
}
}
# Write next header.
if(($report.result.numberTestsTotal -ne 0) -and ($startedTests -eq $false)) {
$startedTests = $true
Write-Host -ForegroundColor green "`n`n:: Running tests ::"
}
# Write Test progress
if($report.result.numberTestsTotal -ne 0 -and $testsRemaining -ne 0) {
$testRatio = [Math]::Ceiling((100 * ($report.result.numberTestsCompleted / $report.result.numberTestsTotal)))
$testsRemaining = $report.result.numberTestsTotal - $report.result.numberTestErrors - $report.result.numberTestsCompleted
Write-Host -NoNewLine "`rTests passed: " $testRatio "% | Tests remaining: " $testsRemaining
}
if($testsRemaining -eq 0 -and $report.result.numberTestErrors -gt 0) {
Write-Host -ForegroundColor red "`nERROR: $($report.result.numberTestErrors) tests have failed"
exit
}
} while(($report.result.status -eq "InProgress") -or ($report.result.status -eq "Pending"))
# FAILED DEPLOYMENT ANALYSIS
if($report.result.status -eq "Failed") {
Write-Host -ForegroundColor red "`n`nERROR Deployment Failed!"
$report = sfdx force:mdapi:deploy:report -i $deployJobId --json --verbose 2>&1 | ConvertFrom-Json
foreach($failure in $report.result.details.componentFailures) {
Write-Host -ForegroundColor red "`t - " $failure.problem
}
exit
}
# SUCCESSFUL DEPLOYMENT MESSAGE
Write-Host -ForegroundColor green "`n:: Deployment Successful! ::"