Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install-Module doc doesn't address handling of declared dependencies #4383

Closed
4 of 8 tasks
travisclagrone opened this issue Jun 1, 2019 · 7 comments
Closed
4 of 8 tasks
Labels
area-powershellget Area - PowerShellGet module

Comments

@travisclagrone
Copy link
Contributor

travisclagrone commented Jun 1, 2019

Issue Details

The reference documentation for the Install-Module cmdlet of the PowerShellGet module does not address how declared dependencies are handled when a module is installed (i.e. the "RequiredAssemblies" and "RequiredModules" fields of a module manifest).

Context

This topic is actually touched on in the reference documentation for the -RequiredAssemblies and -RequiredModules parameters of the New-ModuleManifest cmdlet of the Microsoft.PowerShell.Core module. However, it is only with respect to importing and not installing. Moreover, this topic deserves attention in the doc of [Install-Module], which is what actually implements the behavior in question.

More perniciously, I have observed (albeit anecdotally) that PowerShell's behavior of not strongly resolving dependencies at installation-time, but rather weakly resolving dependencies at import-time, can be a cause of confusion. This is particularly when compared to the languages that many new adopters hail from, as their package management facilities more commonly resolve and install dependencies contemporaneously with the installation of the dependent (e.g. pip, npm, and evendotnet).

Proposal

In this context, the band-aid solution of appending a short clarifying statement to Install-Module's Notes seems likely to be ineffective.

A much more effective solution would encompass (1) a simple statement early in the Description; (2) a ''loud'' warning box with a more forward admonition in the Notes; and (3) a cautionary counter-example with subsequent correction in the Examples.

Finally, a broader resolution might require a short-and-pointed standalone About article that orients newcomers to dependency resolution practices around PowerShell Core (PowerShellGet, other PackageManagement, scripts vs. modules, manifests metadata, #Requires directives, etc.), and then builds off that to conclude by cementing a standard (or at least recommended best practice) for contributors.

I would propose the second of these three possible solutions for practicality's sake. However, fostering a conversation about dependency resolution designs around the PowerShell language is needed.

E.g. ScriptFileInfo's idiosyncratic distinction between "required" and "external"; reconciling #Requires directives and Import- cmdlets; dynamic-but-fragile metadata-based resolution at runtime vs. secure-but-heavy packaging at publish-time, etc.

Version(s) of document impacted

  • Impacts 7 document
  • Impacts 6 document
  • Impacts 5.1 document
  • NA Impacts 5.0 document
  • NA Impacts 4.0 document
  • NA Impacts 3.0 document

Reason(s) for not selecting all version of documents

  • The documented feature was introduced in selected version of PowerShell
  • This issue only shows up in selected version of the document
@sdwheeler
Copy link
Contributor

@SydneyhSmith Can you comment on this issue?

@sdwheeler sdwheeler added the area-powershellget Area - PowerShellGet module label Jun 3, 2019
@SphenicPaul
Copy link

SphenicPaul commented Jun 5, 2019

I was in the process of raising the same (similar) point until I saw this 'issue'. See below...

Missing Documentation and/or Defect?
There does not appear to be any information that identifies behaviour of auto-importing of PSModules that are listed as 'RequiredModules' within a PSModule manifest (.psd1).

For example, if I have 2 PSModules:

  • ModuleA
  • ModuleB

... and ModuleB (v55.0.0, for example) has ModuleA listed in the 'RequiredModules' property of the PSModule manifest (to indicate that ModuleB depends on ModuleA), with a specific version of ModuleA detailed (e.g. ModuleVersion = '1.0.0'), like so...

RequiredModules = @(@{ModuleName = 'ModuleA'; GUID = '29a19549-168b-4531-a562-b357e111111d'; ModuleVersion = '1.0.0'; })

... then it's not clear (and not documented) that when running...

Install-Module 'ModuleA' -RequiredVersion '55.0.0'

... this will (assuming both exist in a PSRepository) install both 'ModuleA' (version '55.0.0') and also 'ModuleB' ... although the version of ModuleB might be:

  • a) v1.0.0 (the same version as the one depended upon, if it's the latest version), or;
  • b) A later version of the same Module, if present

I'd argue the documentation isn't clear on this behaviour, and in addition, the 'Install-Module' could be importing later versions of a depended-upon module, rather than the specific version that is depended on (which means that you're potentially installing, then importing/using incorrect combinations of PowerShell module dependencies).

For example, if I've tested with:

  • 'ModuleA' v1.0.0
  • 'ModuleB' v55.0.0

..my installation/import as part of a process/script I had written (and had thought to be previously tested and working already) could actually be using (or trying to use):

  • 'ModuleA' v2.0.0
  • 'ModuleB' v55.0.0

... which has a breaking change in 'ModuleA' that I've released and published but do not want to be used with 'ModuleB' v55.0.0.

It seems to always mean that you get the "wrong" (non-specified/required) version of a depended-upon PSModule if later versions exist. I'd like to see this behaviour default to import the actual, required version if a 'ModuleVersion' is specified in the module manifest (i.e. lowest version required, not highest version required).

Real World Example/Problem
The real-world example/problem I have is that... I've DSC Resources in ModuleB that depend on DSC resources in ModuleA. The Resources in ModuleB have the specific version of the ModuleA PSModule set in the Import-DSCResource call/usage in order to avoid errors when multiple versions of the module exist on the server/host.

However, when I run Install-Module and then Import-Module, specifying the exact version of ModuleB, a later version of ModuleA is being installed, and then imported, and thus the DSC Resource can't/won't run because the correct PSModule hasn't been installed as part of the 'Install-Module' (it's installed, and thus then imported a later version instead - a version that wasn't the one specified in the DSC Resource).

Workarounds
Are there any nice workarounds for this? Nesting all modules into a parent one doesn't seem a nice option.

Hope that makes sense - Shout/tag if you've any questions.

EDIT: Just updated some of the points to try and get terminology correct (i.e. import/install etc.) and versions/dependencies the correct way around.

@SphenicPaul
Copy link

In addition, NuGet 'Restore' seems to use "Lowest applicable version"...

https://docs.microsoft.com/en-us/nuget/consume-packages/dependency-resolution

@sdwheeler sdwheeler added the review-shiproom Waiting - for Shiproom discussion label Jun 19, 2019
@sdwheeler
Copy link
Contributor

@SydneyhSmith Can you comment on this issue?

@SydneyhSmith
Copy link
Contributor

Thanks for the feedback @SphenicPaul and @travis-c-lagrone I appreciate the thoughtful comments
and I apologize for the delayed response.
There's a lot here and a lot that could be improved--here are some of my thoughts:

  • Ideally, only the publisher should really have to worry about the dependency structure, and they
    should be empowered to manage their dependencies in such a way that the end user does not have to worry about the dependency structure at all
  • There is a lot of room for improvement in this aspect of the documentation for publishing packages
    As you suggest, we should better document the dependency structure, and the possible problems users could run into/various dependency management scenarios
  • There could be a note added to Install-Module documentation explaining that the specified dependent modules will be downloaded as well
  • From an interactive command line experience, the user may want to know both the name and version of dependent modules that are downloaded
    • In the current experience there are two ways this happens:
      • The name of the module flashes in the status bar when it is being downloaded
      • With the -Verbose parameter both the name and the version of the module loaded are shown, but since this is mixed in with other information it is not obviously discoverable
    • Would it be useful to have another way to show what is downloaded? Automatic warnings?
      A -ShowDependencies switch?
  • There is potential for a larger discussion on how the version of the module is chosen to be downloaded.
    Currently there is an RFC out for PowerShellGet 3.0, this is likely the best forum for this discussion:
    https://github.com/PowerShell/PowerShell-RFC/pull/185/files#diff-661062766ee198277a334922a903752e

@sdwheeler sdwheeler added Waiting-PowerShell-Team and removed review-shiproom Waiting - for Shiproom discussion labels Aug 8, 2019
@sdwheeler
Copy link
Contributor

@SydneyhSmith Can you summarize the changes need to the docs or submit a PR? You said that the changes should probably go in the "publishing" docs.

@SydneyhSmith
Copy link
Contributor

Thanks @sdwheeler I have opened PR #4625 to address this item

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-powershellget Area - PowerShellGet module
Projects
None yet
Development

No branches or pull requests

4 participants