1

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:

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:

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

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. If bootstrap does contain a Install-Module, maybe you can share the yaml and the boostrap either here or in a gist? – Michael Erpenbeck Nov 17 '20 at 4:31
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 @Michael Erpenbeck 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.