PowerShell Script to deploy repository to Salesforce

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












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:



  1. 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)


  2. Authenticates against Salesforce


  3. Deploys all the repository and polls the server to update the status in the console


  4. Runs the test and keeps polling to update the visual status


  5. 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 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


# SUCCESSFUL DEPLOYMENT MESSAGE
Write-Host -ForegroundColor green "`n:: Deployment Successful! ::"






share|improve this question

























    up vote
    1
    down vote

    favorite












    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:



    1. 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)


    2. Authenticates against Salesforce


    3. Deploys all the repository and polls the server to update the status in the console


    4. Runs the test and keeps polling to update the visual status


    5. 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 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


    # SUCCESSFUL DEPLOYMENT MESSAGE
    Write-Host -ForegroundColor green "`n:: Deployment Successful! ::"






    share|improve this question





















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      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:



      1. 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)


      2. Authenticates against Salesforce


      3. Deploys all the repository and polls the server to update the status in the console


      4. Runs the test and keeps polling to update the visual status


      5. 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 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


      # SUCCESSFUL DEPLOYMENT MESSAGE
      Write-Host -ForegroundColor green "`n:: Deployment Successful! ::"






      share|improve this question











      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:



      1. 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)


      2. Authenticates against Salesforce


      3. Deploys all the repository and polls the server to update the status in the console


      4. Runs the test and keeps polling to update the visual status


      5. 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 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


      # SUCCESSFUL DEPLOYMENT MESSAGE
      Write-Host -ForegroundColor green "`n:: Deployment Successful! ::"








      share|improve this question










      share|improve this question




      share|improve this question









      asked Aug 3 at 6:40









      Javier García Manzano

      2007




      2007




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          In parameters for your script, you usually want a [switch] instead of [bool]. It's more convenient to use when launching the script and works the same way in the script.



          Since your script doesn't work without a repositoryDirectory, you should make this a mandatory parameter. PowerShell provides a lot of convenient error handling out of the box if you annotate your parameters properly.



          param(
          [parameter(Mandatory=$true)] [string] $RepositoryDirectory,
          [switch] $IsProduction
          )

          PS> .Deploy-SF.ps1 'Repository' -IsProduction


          Write-Host is generally frowned upon. It keeps the text out of the standard stream and is strictly for display in the console. You can't capture this text in a log file for example, by redirecting the script output. Here you use it for colored text, which is a reason. But if you can get by without the green text, you can simply put your string as a statement on a line. It will get end up in the output stream automatically. And PowerShell expands variables automatically inside of double quotes.



          # instead of
          Write-Host "Tests passed: " $testRatio "% | Tests remaining: " $testsRemaining
          # use
          "Tests passed: $testRatio% | Tests remaining: $testsRemaining"
          # wrap complex expressions in $()
          "Time = $($Some.Object.Duration()) Hours"


          If you want to do fancy tricks with overwriting the same line repeatedly, you can do as you did or read and write $Host.UI.RawUI.CursorPosition.



          You can display a progress bar and some additional info using Write-Progress.



          Don't use red text for errors. Use Write-Warning, Write-Error or throw accordingly (depending on if you want a terminating error or not).



          Use PowerShell commandlets instead of .NET classes whenever possible. It's easier to read, parameters are easily discoverable etc.



          # instead of
          [System.IO.File]::Exists($path)
          [System.IO.Path]::Combine($srcDirectory,"package.xml")
          # use
          Test-Path $path
          Join-Path $srcDirectory "package.xml"





          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200870%2fpowershell-script-to-deploy-repository-to-salesforce%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            In parameters for your script, you usually want a [switch] instead of [bool]. It's more convenient to use when launching the script and works the same way in the script.



            Since your script doesn't work without a repositoryDirectory, you should make this a mandatory parameter. PowerShell provides a lot of convenient error handling out of the box if you annotate your parameters properly.



            param(
            [parameter(Mandatory=$true)] [string] $RepositoryDirectory,
            [switch] $IsProduction
            )

            PS> .Deploy-SF.ps1 'Repository' -IsProduction


            Write-Host is generally frowned upon. It keeps the text out of the standard stream and is strictly for display in the console. You can't capture this text in a log file for example, by redirecting the script output. Here you use it for colored text, which is a reason. But if you can get by without the green text, you can simply put your string as a statement on a line. It will get end up in the output stream automatically. And PowerShell expands variables automatically inside of double quotes.



            # instead of
            Write-Host "Tests passed: " $testRatio "% | Tests remaining: " $testsRemaining
            # use
            "Tests passed: $testRatio% | Tests remaining: $testsRemaining"
            # wrap complex expressions in $()
            "Time = $($Some.Object.Duration()) Hours"


            If you want to do fancy tricks with overwriting the same line repeatedly, you can do as you did or read and write $Host.UI.RawUI.CursorPosition.



            You can display a progress bar and some additional info using Write-Progress.



            Don't use red text for errors. Use Write-Warning, Write-Error or throw accordingly (depending on if you want a terminating error or not).



            Use PowerShell commandlets instead of .NET classes whenever possible. It's easier to read, parameters are easily discoverable etc.



            # instead of
            [System.IO.File]::Exists($path)
            [System.IO.Path]::Combine($srcDirectory,"package.xml")
            # use
            Test-Path $path
            Join-Path $srcDirectory "package.xml"





            share|improve this answer



























              up vote
              0
              down vote













              In parameters for your script, you usually want a [switch] instead of [bool]. It's more convenient to use when launching the script and works the same way in the script.



              Since your script doesn't work without a repositoryDirectory, you should make this a mandatory parameter. PowerShell provides a lot of convenient error handling out of the box if you annotate your parameters properly.



              param(
              [parameter(Mandatory=$true)] [string] $RepositoryDirectory,
              [switch] $IsProduction
              )

              PS> .Deploy-SF.ps1 'Repository' -IsProduction


              Write-Host is generally frowned upon. It keeps the text out of the standard stream and is strictly for display in the console. You can't capture this text in a log file for example, by redirecting the script output. Here you use it for colored text, which is a reason. But if you can get by without the green text, you can simply put your string as a statement on a line. It will get end up in the output stream automatically. And PowerShell expands variables automatically inside of double quotes.



              # instead of
              Write-Host "Tests passed: " $testRatio "% | Tests remaining: " $testsRemaining
              # use
              "Tests passed: $testRatio% | Tests remaining: $testsRemaining"
              # wrap complex expressions in $()
              "Time = $($Some.Object.Duration()) Hours"


              If you want to do fancy tricks with overwriting the same line repeatedly, you can do as you did or read and write $Host.UI.RawUI.CursorPosition.



              You can display a progress bar and some additional info using Write-Progress.



              Don't use red text for errors. Use Write-Warning, Write-Error or throw accordingly (depending on if you want a terminating error or not).



              Use PowerShell commandlets instead of .NET classes whenever possible. It's easier to read, parameters are easily discoverable etc.



              # instead of
              [System.IO.File]::Exists($path)
              [System.IO.Path]::Combine($srcDirectory,"package.xml")
              # use
              Test-Path $path
              Join-Path $srcDirectory "package.xml"





              share|improve this answer

























                up vote
                0
                down vote










                up vote
                0
                down vote









                In parameters for your script, you usually want a [switch] instead of [bool]. It's more convenient to use when launching the script and works the same way in the script.



                Since your script doesn't work without a repositoryDirectory, you should make this a mandatory parameter. PowerShell provides a lot of convenient error handling out of the box if you annotate your parameters properly.



                param(
                [parameter(Mandatory=$true)] [string] $RepositoryDirectory,
                [switch] $IsProduction
                )

                PS> .Deploy-SF.ps1 'Repository' -IsProduction


                Write-Host is generally frowned upon. It keeps the text out of the standard stream and is strictly for display in the console. You can't capture this text in a log file for example, by redirecting the script output. Here you use it for colored text, which is a reason. But if you can get by without the green text, you can simply put your string as a statement on a line. It will get end up in the output stream automatically. And PowerShell expands variables automatically inside of double quotes.



                # instead of
                Write-Host "Tests passed: " $testRatio "% | Tests remaining: " $testsRemaining
                # use
                "Tests passed: $testRatio% | Tests remaining: $testsRemaining"
                # wrap complex expressions in $()
                "Time = $($Some.Object.Duration()) Hours"


                If you want to do fancy tricks with overwriting the same line repeatedly, you can do as you did or read and write $Host.UI.RawUI.CursorPosition.



                You can display a progress bar and some additional info using Write-Progress.



                Don't use red text for errors. Use Write-Warning, Write-Error or throw accordingly (depending on if you want a terminating error or not).



                Use PowerShell commandlets instead of .NET classes whenever possible. It's easier to read, parameters are easily discoverable etc.



                # instead of
                [System.IO.File]::Exists($path)
                [System.IO.Path]::Combine($srcDirectory,"package.xml")
                # use
                Test-Path $path
                Join-Path $srcDirectory "package.xml"





                share|improve this answer















                In parameters for your script, you usually want a [switch] instead of [bool]. It's more convenient to use when launching the script and works the same way in the script.



                Since your script doesn't work without a repositoryDirectory, you should make this a mandatory parameter. PowerShell provides a lot of convenient error handling out of the box if you annotate your parameters properly.



                param(
                [parameter(Mandatory=$true)] [string] $RepositoryDirectory,
                [switch] $IsProduction
                )

                PS> .Deploy-SF.ps1 'Repository' -IsProduction


                Write-Host is generally frowned upon. It keeps the text out of the standard stream and is strictly for display in the console. You can't capture this text in a log file for example, by redirecting the script output. Here you use it for colored text, which is a reason. But if you can get by without the green text, you can simply put your string as a statement on a line. It will get end up in the output stream automatically. And PowerShell expands variables automatically inside of double quotes.



                # instead of
                Write-Host "Tests passed: " $testRatio "% | Tests remaining: " $testsRemaining
                # use
                "Tests passed: $testRatio% | Tests remaining: $testsRemaining"
                # wrap complex expressions in $()
                "Time = $($Some.Object.Duration()) Hours"


                If you want to do fancy tricks with overwriting the same line repeatedly, you can do as you did or read and write $Host.UI.RawUI.CursorPosition.



                You can display a progress bar and some additional info using Write-Progress.



                Don't use red text for errors. Use Write-Warning, Write-Error or throw accordingly (depending on if you want a terminating error or not).



                Use PowerShell commandlets instead of .NET classes whenever possible. It's easier to read, parameters are easily discoverable etc.



                # instead of
                [System.IO.File]::Exists($path)
                [System.IO.Path]::Combine($srcDirectory,"package.xml")
                # use
                Test-Path $path
                Join-Path $srcDirectory "package.xml"






                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited 3 hours ago


























                answered 3 hours ago









                Swonkie

                1284




                1284






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200870%2fpowershell-script-to-deploy-repository-to-salesforce%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Python Lists

                    Aion

                    JavaScript Array Iteration Methods