gaelcolas / Sampler

Module template with build pipeline and examples, including DSC elements.
MIT License
171 stars 42 forks source link

Pack step fails if the module requires a module that in turn requires another module #447

Open ykuijs opened 1 year ago

ykuijs commented 1 year ago

Problem description

I create a new module based on Sampler using this code:

When I configure this module to require a module that in turns requires another module, the Pack step fails with the error that the dependency cannot be resolved. When I remove the entry from the RequiredModules property or add modules that do not have any RequiredModules themselves, all works well.

I have traced back the error to these lines of code: https://github.com/gaelcolas/Sampler/blob/b2fc9fb6841108304ca16b80c57f6f51535defc8/.build/tasks/release.module.build.ps1#L296-L313 These lines are causing the issue. When I remove them, the Pack step runs as expected. So, not sure why the Required Modules need to get published before publishing the actual module.

Verbose logs

Built module's Manifest found at C:\Temp\MySimpleModule\output\module\MySimpleModule\1.23.1108.1\MySimpleModule.psd1
  Packaging Required Module DscBuildHelpers v0.2.1
ERROR: PowerShellGet cannot resolve the module dependency 'xDscResourceDesigner' of the module 'DscBuildHelpers' on the repository 'output'. Verify that the dependent module 'xDscResourceDesigner' is available in the repository 'output'. If this dependent 
module 'xDscResourceDesigner' is managed externally, add it to the ExternalModuleDependencies entry in the PSData section of the module manifest.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\2.2.5\PSModule.psm1:10990 char:17
+ ...             Publish-PSArtifactUtility @PublishPSArtifactUtility_Param ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At C:\Temp\MySimpleModule\output\RequiredModules\Sampler\0.117.0\tasks\release.module.build.ps1:246 char:1
+ task package_module_nupkg {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build FAILED. 9 tasks, 1 errors, 0 warnings 00:00:10.1465554
Publish-PSArtifactUtility : PowerShellGet cannot resolve the module dependency 'xDscResourceDesigner' of the module 'DscBuildHelpers' on the repository 'output'. Verify that the dependent module 'xDscResourceDesigner' is available in the repository 'outpu
t'. If this dependent module 'xDscResourceDesigner' is managed externally, add it to the ExternalModuleDependencies entry in the PSData section of the module manifest.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\2.2.5\PSModule.psm1:10990 char:17
+ ...             Publish-PSArtifactUtility @PublishPSArtifactUtility_Param ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Publish-PSArtifactUtility], InvalidOperationException
    + FullyQualifiedErrorId : UnableToResolveModuleDependency,Publish-PSArtifactUtility

How to reproduce

  1. Create a new module
    
    $newSampleModuleParameters = @{
    DestinationPath   = 'C:\Temp'
    ModuleType        = 'SimpleModule'
    ModuleName        = 'MySimpleModule'
    ModuleAuthor      = 'My Name'
    ModuleDescription = 'MySimpleModule Description'
    }

New-SampleModule @newSampleModuleParameters

2. Edit the module PSD1 file in the source folder and replace line 54 (RequiredModules) with ```RequiredModules      = @('DscBuildHelpers', @{ModuleName='DscBuildHelpers'; RequiredVersion='0.2.1'; GUID='23ccd4bf-0a52-4077-986f-c153893e5a6a'})``` 
3. Run the `.\build.ps1 -Tasks noop -ResolveDependency` to download all dependencies
4. Then run the `.\build.ps1 -Tasks Pack` command. This will fail with the specified error.

### Expected behavior

Create a NuGet package successfully

### Current behavior

The code throws the mentioned error and fails.

### Suggested solution

Not sure why the earlier mentioned lines are even in there. When I remove them, the Pack steps completes successfully and a package is created.

### Operating system the target node is running

```text
OsName               : Microsoft Windows 11 Enterprise
OsOperatingSystemSKU : EnterpriseEdition
OsArchitecture       : 64-bit
WindowsVersion       : 2009
WindowsBuildLabEx    : 22621.1.amd64fre.ni_release.220506-1250
OsLanguage           : en-US
OsMuiLanguages       : {en-US, en-GB, nl-NL}

PowerShell version and build the target node is running

Name                           Value                                                                                                                                                                                                                           
----                           -----                                                                                                                                                                                                                           
PSVersion                      5.1.22621.2428                                                                                                                                                                                                                  
PSEdition                      Desktop                                                                                                                                                                                                                         
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                                                                                                                                         
BuildVersion                   10.0.22621.2428                                                                                                                                                                                                                 
CLRVersion                     4.0.30319.42000                                                                                                                                                                                                                 
WSManStackVersion              3.0                                                                                                                                                                                                                             
PSRemotingProtocolVersion      2.3                                                                                                                                                                                                                             
SerializationVersion           1.1.0.1

Module version used

0.117.0
johlju commented 1 year ago

I can reproduce it, but had to add DscBuildHelpers to the RequiredModules.psd1. Also added xDscResourceDesigner just to verify it still failed, and added PowerShellGet to get the latest version since my macOS has 2.2.3 installed instead of 2.2.5. But made no difference.

    DscBuildHelpers             = 'latest'
    xDscResourceDesigner        = 'latest'
    PowerShellGet               = 'latest'

So the code you are referring looks like it is meant to "copy" a required module that is listed in the module manifest from a path of $PSModulePath to output but only if it is not already available in output. It does the "copying" by adding a local folder (PS)Repository, if it does not find the module in the local folder repository it tries to find it in $PSModulePath then it publishes it to the local folder repository. Honestly, I do not know why it need to do that. That locally published module does not seem to be published to the Gallery together with the actual module anyway. I'm thinking this is old code that have no purpose no longer. 🤔

The reason it fails seems to be that (at least in macOS) it does not work using a local folder repository. I can't get Find-Module to work:

/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule>     $RepositoryParams = @{    
>>         Name            = 'output'
>>         SourceLocation  = (Resolve-Path -Path './output/RequiredModules').Path + '/'
>>         PublishLocation = (Resolve-Path -Path './output/RequiredModules').Path + '/'
>>         ErrorAction     = 'Stop'
>>     }
/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule> Register-PSRepository @RepositoryParams                         
/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule> Get-PSRepository                       

Name                      InstallationPolicy   SourceLocation
----                      ------------------   --------------
output                    Untrusted            /Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule/output/RequiredModule…
PSGallery                 Untrusted            https://www.powershellgallery.com/api/v2

/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule> (Get-PSRepository).SourceLocation                               
/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule/output/RequiredModules/
https://www.powershellgallery.com/api/v2
/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule> ls (Get-PSRepository).SourceLocation[0]
ChangelogManagement Metadata        PackageManagement   PowerShellGet       xDSCResourceDesigner
Configuration       ModuleBuilder       Pester          Sampler
DscBuildHelpers     PSDepend        Plaster         Sampler.GitHubTasks
InvokeBuild     PSScriptAnalyzer    PowerShellForGitHub powershell-yaml
/Users/johlju/source/HelpUsers/debug-sampler/MySimpleModule> Find-Module -Name 'Sampler' -repository output -ErrorAction Stop
Find-Package: No match was found for the specified search criteria and module name 'Sampler'. Try Get-PSRepository to see all available
registered module repositories.
johlju commented 1 year ago

Also, there is a bug that if this code should actually be there, it should handle unregister the output repository whenever the task fails. The repository name output should probably be sampler_pack_output or something that is not likely for a user to have named one (since we unregistering it).