Answers: <p>I'm not familiar with Invoke-Build, but appearantly it's a part of the InvokeBuild PowerShell module? In that case, you'll have to install the module as part of the script where you're using it. Your YAML should be something like this:</p>
  <pre><code>- stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              targetType: 'inline'
              script: |
                Install-Module InvokeBuild
                Invoke-Build build
  </code></pre>
  <p>As @Michael Erpenbeck said &quot;the hosted agent starts off as a clean slate&quot;. That is to say that it starts off as a clean slate for each job in your pipeline. I'm not sure what bootstrap.ps1 is supposed to do so I can't really comment on whether that script and your <code>Invoke-Build</code> should be run as steps in the same job. But the main point to remember is that any requirements beyond what the standard Azure Pipelines agents offer should be taken care off within each job.</p>
  
Answers: CC BY-SA 4.0
Answers: 2021-04-13T09:54:32.503Z
Answers: 2021-04-13T09:54:32.503Z
Answers: Walter Vos
Body: <p>I'm trying to build a PowerShell module in an Azure pipeline (dev.azure.com).</p>
  <p>I've setup an initial pipeline and then building it up incrementally in small steps, because inexplicable errors are encountered far too easily on Azure.</p>
  <p>I've added a 'Prepare' stage:</p>
  <pre class="lang-yaml prettyprint-override"><code>name: $(Build.DefinitionName)_$(Date:yyyyMMdd))
  
  trigger:
  - master
  
  pool:
    vmImage: 'ubuntu-latest'
  
  variables:
    major: 0
    minor: 0
    patch: $(Build.BuildID)
    buildVersion: $(major).$(minor).$(patch)
  
  stages:
  - stage: Prepare
    jobs:
      - job: Prepare
        steps:
        - powershell: .\bootstrap.ps1
          displayName: 'Install pre-requisites'
  </code></pre>
  <p>This is based on the original yaml that you get by default when you start a new Pipeline, so the part invoking the bootstrap file is what I got generated for free (This part works ok).</p>
  <p>The bootstrap uses a dependencies file into which you can declare your dependencies and these are subsequently imported. One of those dependencies is InvokeBuild which contains the Invoke-Build command. So I would expect to be able to use the Invoke-Build command in subsequent stages.</p>
  <p>The next part of the yaml pipeline is as follows:</p>
  <pre class="lang-yaml prettyprint-override"><code>- stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              targetType: 'inline'
              script: 'invoke-build build'
  </code></pre>
  <p>The <em>invoke-build build</em>, in itself is ok and valid and works on a local host.</p>
  <p>The <em>Build</em> job fails with the following error:</p>
  <pre><code>/usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command . '/home/vsts/work/_temp/edb3758b-8e16-448d-bea2-9ba18acb9693.ps1'
  Invoke-Build: /home/vsts/work/1/s/do-build.ps1:3
  Line |
     3 |  Invoke-Build build
       |  ~~~~~~~~~~~~
       | The term 'Invoke-Build' is not recognized as the name of a
       | cmdlet, function, script file, or operable program. Check the
       | spelling of the name, or if a path was included, verify that
       | the path is correct and try again.
  </code></pre>
  <p>I discovered there is another way to invoke the build with the PowerShell@2 task using the <em>filePath</em> input:</p>
  <pre><code>- stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              filePath: '$(System.DefaultWorkingDirectory)/do-build.ps1'
  </code></pre>
  <p>the do-build.ps1 script is defined as:</p>
  <pre><code>Set-Location .\Elizium.FakeBuddy
  Invoke-Build build
  </code></pre>
  <p>(Elizium.FakeBuddy is the name of my PowerShell test module being built and that directory contains the <em>InvokeBuild</em> build script)</p>
  <p>but this fails with the exact same error.</p>
  <p>So why is the <em>invoke-build</em> command not available in the PowerShell session at the build stage, even though the Prepare stage has already imported the module?</p>
  <p>The only thing I can think of is that different stages somehow don't share the same PowerShell session, but I don't know if this is correct, this seems unlikely, it doesn't make sense that different stages don't share the same session.</p>
  <p>EDIT: I tried an alternative version where the Build job is declared inside the same stage as Prepare, but this makes no difference, still a problem with Invoke-Build command.</p>
  
Comments: CC BY-SA 4.0
Comments: 2020-11-17T04:31:57.223Z
Comments: Is bootstrap.ps1 doing an `Install-Module InvokeBuild`?  If not, it would explain why you see a problem on the MS Hosted Agent but not on your localhost, since the hosted agent starts off as a clean slate.  You can see an [example here](https://github.com/microsoft/PSRule/blob/main/.azure-pipelines/pipeline-deps.ps1).  
  
  If bootstrap does contain a `Install-Module`, maybe you can share the yaml and the boostrap either here or in a [gist](http://gist.github.com)?
Comments: Michael Erpenbeck
Tags: <azure-devops><azure><azure-pipelines><powershell>
Title: Azure Pipeline PowerShell@2 Task can't run 'invoke-build' command as inline script (build PowerShell Module)
UserDisplayName: Plastikfan
ThreadText: # Azure Pipeline PowerShell@2 Task can't run 'invoke-build' command as inline script (build PowerShell Module)
  
  (Asked by: username_0 on 2020-08-09)
  
  I'm trying to build a PowerShell module in an Azure pipeline (dev.azure.com).
  
  I've setup an initial pipeline and then building it up incrementally in small steps, because inexplicable errors are encountered far too easily on Azure.
  
  I've added a 'Prepare' stage:
  
  ```yaml
  name: $(Build.DefinitionName)_$(Date:yyyyMMdd))
  
  trigger:
  - master
  
  pool:
    vmImage: 'ubuntu-latest'
  
  variables:
    major: 0
    minor: 0
    patch: $(Build.BuildID)
    buildVersion: $(major).$(minor).$(patch)
  
  stages:
  - stage: Prepare
    jobs:
      - job: Prepare
        steps:
        - powershell: .\bootstrap.ps1
          displayName: 'Install pre-requisites'
  
  ```
  
  This is based on the original yaml that you get by default when you start a new Pipeline, so the part invoking the bootstrap file is what I got generated for free (This part works ok).
  
  The bootstrap uses a dependencies file into which you can declare your dependencies and these are subsequently imported. One of those dependencies is InvokeBuild which contains the Invoke-Build command. So I would expect to be able to use the Invoke-Build command in subsequent stages.
  
  The next part of the yaml pipeline is as follows:
  
  ```yaml
  - stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              targetType: 'inline'
              script: 'invoke-build build'
  
  ```
  
  The *invoke-build build*, in itself is ok and valid and works on a local host.
  
  The *Build* job fails with the following error:
  
  ```
  /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command . '/home/vsts/work/_temp/edb3758b-8e16-448d-bea2-9ba18acb9693.ps1'
  Invoke-Build: /home/vsts/work/1/s/do-build.ps1:3
  Line |
     3 |  Invoke-Build build
       |  ~~~~~~~~~~~~
       | The term 'Invoke-Build' is not recognized as the name of a
       | cmdlet, function, script file, or operable program. Check the
       | spelling of the name, or if a path was included, verify that
       | the path is correct and try again.
  
  ```
  
  I discovered there is another way to invoke the build with the PowerShell@2 task using the *filePath* input:
  
  ```
  - stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              filePath: '$(System.DefaultWorkingDirectory)/do-build.ps1'
  
  ```
  
  the do-build.ps1 script is defined as:
  
  ```
  Set-Location .\Elizium.FakeBuddy
  Invoke-Build build
  
  ```
  
  (Elizium.FakeBuddy is the name of my PowerShell test module being built and that directory contains the *InvokeBuild* build script)
  
  but this fails with the exact same error.
  
  So why is the *invoke-build* command not available in the PowerShell session at the build stage, even though the Prepare stage has already imported the module?
  
  The only thing I can think of is that different stages somehow don't share the same PowerShell session, but I don't know if this is correct, this seems unlikely, it doesn't make sense that different stages don't share the same session.
  
  EDIT: I tried an alternative version where the Build job is declared inside the same stage as Prepare, but this makes no difference, still a problem with Invoke-Build command.
  
  **Tags:** azure-devops, azure, azure-pipelines, powershell
  
  > **Comments:**
  > **username_1**: Is bootstrap.ps1 doing an `Install-Module InvokeBuild`?  If not, it would explain why you see a problem on the MS Hosted Agent but not on your localhost, since the hosted agent starts off as a clean slate.  You can see an [example here](https://github.com/microsoft/PSRule/blob/main/.azure-pipelines/pipeline-deps.ps1).    If bootstrap does contain a `Install-Module`, maybe you can share the yaml and the boostrap either here or in a [gist](http://gist.github.com)?  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2021-04-13. Score: 1
  
  I'm not familiar with Invoke-Build, but appearantly it's a part of the InvokeBuild PowerShell module? In that case, you'll have to install the module as part of the script where you're using it. Your YAML should be something like this:
  
  ```
  - stage: Build
    jobs:
      - job: Build
        steps:
          - task: PowerShell@2
            inputs:
              targetType: 'inline'
              script: |
                Install-Module InvokeBuild
                Invoke-Build build
  
  ```
  
  As @username_1 said "the hosted agent starts off as a clean slate". That is to say that it starts off as a clean slate for each job in your pipeline. I'm not sure what bootstrap.ps1 is supposed to do so I can't really comment on whether that script and your `Invoke-Build` should be run as steps in the same job. But the main point to remember is that any requirements beyond what the standard Azure Pipelines agents offer should be taken care off within each job.
  
  
  ---
  
  