Powershell: Test-ModuleManifest doesn't work when RequiredModules are specified

Created on 6 Sep 2018  路  5Comments  路  Source: PowerShell/PowerShell

This is essentially a duplicate of closed issue 3663 which was marked as closed because while it failed in PowerShell 5.1 as the original poster commented, @SteveL-MSFT, indicated this works in PowerShell 6. I can not get it to work in 6.0.4.

I'm unclear as to why the required modules have to be installed locally before publishing. As part of the publishing process, a check is performed to ensure that the required modules are available on the repo. If the required modules are not available on the repo, the publishing of the module fails. If the required modules are found on the repo, the publishing of the module will succeed. With that workflow, why require them to be installed locally?

Steps to reproduce

New-ModuleManifest m.psd1 -RequiredModules sub
Test-ModuleManifest m.psd1 -verbose

Expected behavior

I'd expect it to return details on the module being tested. For example:

Test-ModuleManifest m.psd1 -Verbose

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   0.0.1      m

Actual behavior

I get an error

Test-ModuleManifest m.psd1 -Verbose
Test-ModuleManifest : The specified RequiredModules entry 'sub' in the module manifest 'C:\Inbox\m.psd1' is invalid. Try again after updating this entry with valid values.
At line:1 char:1
+ Test-ModuleManifest m.psd1 -Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (m.psd1:String) [Test-ModuleManifest], DirectoryNotFoundException
+ FullyQualifiedErrorId : Modules_InvalidRequiredModulesinModuleManifest,Microsoft.PowerShell.Commands.TestModuleManifestCommand


ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   0.0.1      m

Environment data

This happens in version 6.0.4 on both Windows and Ubunutu

Windows

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.0.4
PSEdition                      Core
GitCommitId                    v6.0.4
OS                             Microsoft Windows 10.0.14393
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Ubuntu

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.0.4
PSEdition                      Core
GitCommitId                    v6.0.4
OS                             Linux 4.4.0-28-generic #47-Ubuntu SMP Fri Jun...
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Workaround

To get around this limitation, we read in the data file information, create an array of the required modules and install each of them.

    # Get .psd1 data
    $data = Import-PowerShellDataFile .\*.psd1

    # Get the RequiredModules
    $requiredModules = $data.RequiredModules.ModuleName

    if ($requiredModules) {
        # Create credentials used to connect to private NuGet feed
        Write-Output 'Creating credentials'
        $pwd = ConvertTo-SecureString $NuGetApiKey -AsPlainText -Force
        $cred = New-Object Management.Automation.PSCredential ("username", $pwd)
        # Install the required modules
        foreach ($module in $requiredModules) {
            Install-Module $module -Repository $repo -Credential $cred -Verbose
        }
    }

While this works, it adds additional, unneeded overhead.

Area-Cmdlets-Core Resolution-Duplicate

Most helpful comment

@mklement0 - Thanks for the feedback! I didn't see the previously reported bug 7495 . I agree with @rjmholt on all of his points:

  1. It should constrain on version
  2. The error message should be improved
  3. Test-ModuleManifest should have an opt-in for checking just the manifest for being well-formed

If Test-ModuleManifest is updated to have an opt-in, would Publish-Module be updated to check the manifests with that opt-in? I only encountered this issue when attempting to Publish-Module.

Thanks for the link to the stopgap as well. I'll give it a try and update my process accordingly if I can validate it works.

All 5 comments

Another quick follow up, when installing the required modules, you'll notice that I don't specify a version I always just grab the latest. The locally installed version of the required modules does NOT have to match the version specified in the required modules section of the .psd1.

If the workflow is going to force you to have the required modules installed locally, it should additionally ensure it's the correct version.

@cholmes1111:

Good point about not enforcing the version; that bug has already been reported: #7495

That same report, created by @rjmholt, also suggests the following enhancement, which addresses your main issue:

Provide an option to only check the validity of the manifest itself, and not whether it will work in the current session (this last point I think is part of the need to separate "Module manifests that are not well-formed" from "Module manifests that cannot be loaded in the current session"

Note that this means that the default behavior would remain as-is (except for the need to fix the version bug), and that performing a test for mere well-formation would be _opt-in_.


In the meantime, you can use the stopgap demonstrated in this SO answer.

@mklement0 - Thanks for the feedback! I didn't see the previously reported bug 7495 . I agree with @rjmholt on all of his points:

  1. It should constrain on version
  2. The error message should be improved
  3. Test-ModuleManifest should have an opt-in for checking just the manifest for being well-formed

If Test-ModuleManifest is updated to have an opt-in, would Publish-Module be updated to check the manifests with that opt-in? I only encountered this issue when attempting to Publish-Module.

Thanks for the link to the stopgap as well. I'll give it a try and update my process accordingly if I can validate it works.

If you're like me and you've come across this page while searching for a solution to publishing modules from a container (Bitbucket/Azure DevOps) I have a very simple work around to this issue.

Problem

The problem is that Publish-Module runs Test-ModuleManifest which expects any requiredModules (which will include Externally Required modules) to be installed on the local file system. This is especially challenging when your module depends on modules from multiple external repos.

Solution

The thing is that Test-ModuleManifest just looks for the existence of the .psd1 file and doesn't care about the contents. I was able to work around this by simply identifying the location where modules are installed by default and then creating the module directory and an empty .psd1 file like this:

Function Build-RequiredModuleFiles {

  # Get .psd1 data
  $Data = Import-PowerShellDataFile .\*.psd1

  # Get the RequiredModules
  [array]$RequiredModules = $data.RequiredModules


  If ($RequiredModules) {

    Set-Location '/root/.local/share/powershell/Modules'

    # Create the required module manifests
    ForEach ($module in $requiredModules) {
      $moduleName = $module.ModuleName
      New-Item $moduleName -type Directory
      Write-Output "Creating empty .psd1 file for module $modulename at $((Get-Location).Path)\$moduleName\$moduleName.psd1"

      # Create manifest
      New-Item ".\$moduleName\$moduleName.psd1"
    }
  }
}

I think it makes no sense to create a module manifest if it can not be used or tested locally. Don't add RequiredModules if you have to ignore it on next step.

Was this page helpful?
0 / 5 - 0 ratings