<p>After resolving some syntax issues, I found the true cause of failing to throw the error.
In my prior usage I was doing this through Inspec provisioner, which handled the exit codes. </p>

<p>If you are using Pester and having to do the workaround I described above, then to ensure error's in a step are thrown you need to throw an exit code other than 0. </p>

<p>The two steps I took that seem to work fine (I like some emoji fire in my logs )</p>

<pre><code>$ErrorActionPreference = 'Stop'

try 
{
# Do code here
}
catch
{
   Write-Error " Failed to do something important `$TestFile: $TestFile"
  exit 1  # packer will recognize failure at this point
}
</code></pre>

<p>Note that you will want to make sure your Azure DevOps Pipeline has the following settings to publish test results regardless of failing:</p>

<pre class="lang-yaml prettyprint-override"><code># ℹ  Using Invoke-Build to call Packer. You can do this with a packer extension or any other way you prefer
- task: PowerShell@2
  displayName: Run Packer Configuration
  inputs:
      filePath: build/build.ps1
      arguments: '-Task PackerBuild -Configuration $(Configuration)'
      errorActionPreference: 'Continue'
      pwsh: true
  continueOnError: true #I want to publish the test results regardless

- task: PublishTestResults@2
  displayName: Publish Pester Tests
  inputs:
      testResultsFormat: 'NUnit'
      testResultsFiles: '**/TEST-*.xml'
  condition: succeededOrFailed()
</code></pre>

CC BY-SA 4.0
2020-03-11T21:07:32.477Z
2020-03-11T21:07:32.477Z
sheldonhull
<p>I'm building a packer pipeline and having an issue in getting the failure of a powershell provisioner step to fail the packer job itself. This is important as without failing the Packer job, the AMI would be published, despite the test failure.</p>

<p>How I'm proceeding:</p>

<ol>
<li>Run provisioning setup steps</li>
<li>Copy Pester Script to Remote machine</li>
<li>Invoke inline powershell statement to <code>Invoke-Pester</code></li>
<li>Download the test results from the Pester remote run</li>
<li>Next provisioning step parses the file to count errors and throws error upon issue count > 0</li>
</ol>

<p>However, even with issue count being > 0 it is not causing the pipeline to fail. Additionally some errors thrown in other provisioner steps also fail to cause the Packer job to stop. I've set <code>$ErrorActionPreference = 'Stop'</code> on one of them and it didn't seem to make any difference.</p>

<p>Here's part of the provisioning workflow for packer. </p>

<pre><code>...     {
            "type": "file",
            "source": "{{ template_dir }}/tests/windows-server.tests.ps1",
            "destination": "{{ user `TEMP_DIRECTORY` }}/"
        },
        {
            "type": "powershell",
            "environment_vars": [
                "TEMP_DIRECTORY={{ user `TEMP_DIRECTORY` }}/"
            ],
            "inline": [
                "if(-not (Get-InstalledModule Pester -MinimumVersion 4.10.1)){ Install-Module Pester -Scope AllUsers -AllowClobber -Force -verbose} ",
                "Import-Module Pester -MinimumVersion 4.10.1 -Force -DisableNameChecking",
                "$null = New-Item -Path $ENV:TEMP_DIRECTORY -ItemType Directory -Force -ErrorAction SilentlyContinue",
                "$testresult = Invoke-Pester -Script (Join-Path $ENV:TEMP_DIRECTORY 'windows-server.tests.ps1') -OutputFile (Join-Path $ENV:TEMP_DIRECTORY 'TEST-pester-results.xml') -OutputFormat 'NUnitXML' -PassThru"
            ]
        },
        {
            "type": "file",
            "direction": "download",
            "source": "{{ user `TEMP_DIRECTORY` }}/TEST-pester-results.xml",
            "destination": "{{ template_dir }}/artifacts/TEST-pester-results.xml"
        }, ...
</code></pre>

<p>Once this part is done it's followed by this step which is some logic from this blog post: </p>

<pre><code>  {
            "environment_vars": [
                "TEMP_DIRECTORY={{ user `TEMP_DIRECTORY` }}/"
            ],
            "script": "./scripts/Get-TestResults.ps1",
            "type": "powershell"
        },

</code></pre>

<p>The <code>Get-TestResults.ps1</code> has the following function thanks to this article: <a href="https://samcogan.com/testing-packer-images-with-pester" rel="nofollow noreferrer">Testing Packer Images with Pester</a> written originally by <a href="https://stackoverflow.com/users/8768/sam-cogan">Sam Cogan</a> and modified slightly by me.</p>

<pre><code>[cmdletbinding()]
param()
$TestFile = Join-Path $ENV:TEMP_DIRECTORY 'TEST-pester-results.xml'

if (Test-Path -Path $TestFile -PathType Leaf)
{
    [xml]$testResults = Get-Content -Path $TestFile -Raw
    $totalIssues=[int]$($testResults.'test-results'.errors) + [int]$($testResults.'test-results'.failures) + [int]$($testResults.'test-results'.invalid)
    exit $totalIssues
}
else
{
    Write-Error " Failed to find `$TestFile: $TestFile"
    Write-Warning "$(Get-ChildItem $ENV:TEMP_DIRECTORY -Recurse | Format-Table -autosize -wrap | Out-String)"
    Write-Error " Failed to find `$TestFile: $TestFile"
    exit 1  #not a good exit :-)

}

</code></pre>

CC BY-SA 4.0
2020-03-11T19:03:57.860Z
I found one syntax issue when reworking through this, as the default Packer behavior per PowerShell's default behavior is `$ErrorActionPreference = 'continue'` . I set manually now at the top of all my scripts and also fixed a syntax issue on `Get-TestResults` and will see if it works correctly this time. Fingers crossed 
sheldonhull
<azure-devops><packer>
How do fail a Packer pipeline upon powershell provisioner pester test failure?
sheldonhull
# How do fail a Packer pipeline upon powershell provisioner pester test failure?

(Asked by: username_0 on 2020-03-11)

I'm building a packer pipeline and having an issue in getting the failure of a powershell provisioner step to fail the packer job itself. This is important as without failing the Packer job, the AMI would be published, despite the test failure.
How I'm proceeding:

Run provisioning setup steps
Copy Pester Script to Remote machine
Invoke inline powershell statement to Invoke-Pester
Download the test results from the Pester remote run
Next provisioning step parses the file to count errors and throws error upon issue count > 0

However, even with issue count being > 0 it is not causing the pipeline to fail. Additionally some errors thrown in other provisioner steps also fail to cause the Packer job to stop. I've set $ErrorActionPreference = 'Stop' on one of them and it didn't seem to make any difference.
Here's part of the provisioning workflow for packer. 
...     {
            "type": "file",
            "source": "{{ template_dir }}/tests/windows-server.tests.ps1",
            "destination": "{{ user `TEMP_DIRECTORY` }}/"
        },
        {
            "type": "powershell",
            "environment_vars": [
                "TEMP_DIRECTORY={{ user `TEMP_DIRECTORY` }}/"
            ],
            "inline": [
                "if(-not (Get-InstalledModule Pester -MinimumVersion 4.10.1)){ Install-Module Pester -Scope AllUsers -AllowClobber -Force -verbose} ",
                "Import-Module Pester -MinimumVersion 4.10.1 -Force -DisableNameChecking",
                "$null = New-Item -Path $ENV:TEMP_DIRECTORY -ItemType Directory -Force -ErrorAction SilentlyContinue",
                "$testresult = Invoke-Pester -Script (Join-Path $ENV:TEMP_DIRECTORY 'windows-server.tests.ps1') -OutputFile (Join-Path $ENV:TEMP_DIRECTORY 'TEST-pester-results.xml') -OutputFormat 'NUnitXML' -PassThru"
            ]
        },
        {
            "type": "file",
            "direction": "download",
            "source": "{{ user `TEMP_DIRECTORY` }}/TEST-pester-results.xml",
            "destination": "{{ template_dir }}/artifacts/TEST-pester-results.xml"
        }, ...

Once this part is done it's followed by this step which is some logic from this blog post: 
  {
            "environment_vars": [
                "TEMP_DIRECTORY={{ user `TEMP_DIRECTORY` }}/"
            ],
            "script": "./scripts/Get-TestResults.ps1",
            "type": "powershell"
        },


The Get-TestResults.ps1 has the following function thanks to this article: Testing Packer Images with Pester written originally by Sam Cogan and modified slightly by me.
[cmdletbinding()]
param()
$TestFile = Join-Path $ENV:TEMP_DIRECTORY 'TEST-pester-results.xml'

if (Test-Path -Path $TestFile -PathType Leaf)
{
    [xml]$testResults = Get-Content -Path $TestFile -Raw
    $totalIssues=[int]$($testResults.'test-results'.errors) + [int]$($testResults.'test-results'.failures) + [int]$($testResults.'test-results'.invalid)
    exit $totalIssues
}
else
{
    Write-Error " Failed to find `$TestFile: $TestFile"
    Write-Warning "$(Get-ChildItem $ENV:TEMP_DIRECTORY -Recurse | Format-Table -autosize -wrap | Out-String)"
    Write-Error " Failed to find `$TestFile: $TestFile"
    exit 1  #not a good exit :-)

}

**Tags:** azure-devops, packer

> **Comments:**
> **username_0**: I found one syntax issue when reworking through this, as the default Packer behavior per PowerShell's default behavior is `$ErrorActionPreference = 'continue'` . I set manually now at the top of all my scripts and also fixed a syntax issue on `Get-TestResults` and will see if it works correctly this time. Fingers crossed   

---

## 1 answers

### Answer by username_0 on 2020-03-11. Score: 4

After resolving some syntax issues, I found the true cause of failing to throw the error.
In my prior usage I was doing this through Inspec provisioner, which handled the exit codes. 
If you are using Pester and having to do the workaround I described above, then to ensure error's in a step are thrown you need to throw an exit code other than 0. 
The two steps I took that seem to work fine (I like some emoji fire in my logs )
$ErrorActionPreference = 'Stop'

try 
{
# Do code here
}
catch
{
   Write-Error " Failed to do something important `$TestFile: $TestFile"
  exit 1  # packer will recognize failure at this point
}

Note that you will want to make sure your Azure DevOps Pipeline has the following settings to publish test results regardless of failing:
# ℹ  Using Invoke-Build to call Packer. You can do this with a packer extension or any other way you prefer
- task: PowerShell@2
  displayName: Run Packer Configuration
  inputs:
      filePath: build/build.ps1
      arguments: '-Task PackerBuild -Configuration $(Configuration)'
      errorActionPreference: 'Continue'
      pwsh: true
  continueOnError: true #I want to publish the test results regardless

- task: PublishTestResults@2
  displayName: Publish Pester Tests
  inputs:
      testResultsFormat: 'NUnit'
      testResultsFiles: '**/TEST-*.xml'
  condition: succeededOrFailed()


---

