PoshCode / ModuleBuilder

A PowerShell Module to help scripters write, version, sign, package, and publish.
MIT License
445 stars 54 forks source link

When UnversionedOutputDirectory = $true and OutputDirectory = ".." wrong things happen #128

Closed PeterJamesLawson closed 6 months ago

PeterJamesLawson commented 6 months ago

Really excited to find this repo, I'd been creating some tools of my own, but would love to use what you've created.

Unfortunately, I can't get Build-Module to behave as I'd expect it to.

Here is an example...

Project initial state

.MyModule
├── build.psd1
└── Source
        ├── MyModule.psd1
        ├── Private
        └── Public
                └── Some-Function.ps1

build.psd1 @{ ModuleManifest = "./Source/MyModule.psd1" ModuleVersion = '0.0.2' UnversionedOutputDirectory = $true OutputDirectory = ".." }

./Source/MyModule.psd1 @{ ModuleVersion = '0.0.1' }

After executing... PS C:\MyModule> Build-Module build.psd1

.MyModule
├── build.psd1
├── **0.0.2** <-- versioned folder is still created
│      ├── MyModule.psd1
│      └── MyModule.psm1
└── Source
        ├── MyModule.psd1
        ├── Private
        └── Public
                └── Some-Function.ps1

Manifest does not have updated version ./0.0.2/MyModule.psd1 @{ ModuleVersion = '0.0.1' }

There are other permutations of these parameters that do other odd things, and if someone is interested in looking into this, I can give more information.

Environment Powershell 7.4.1 ModuleBuilder 3.1.0

Jaykul commented 6 months ago

What did you expect to happen when you specify the parent folder for output?

Jaykul commented 6 months ago

[Spoilers] Here's why what happened, happened:

ResolveOutputFolder.ps1

  1. All paths except the ModuleManifest are relative to the ModuleManifest. This means that ".." means the folder "C:\MyModule" in your example.
  2. The actual output folder must not be a direct ancestor of the source. Trust me, you don't want that. This is particularly true since the default Target is "CleanBuild" which requires deleting everything in the output folder... (I did, in fact, delete my local source for ModuleBuilder several times before I got a specific check in place for this).
  3. The work around for when the output folder is an ancestor ... is to append a version number. Period.
  4. There's a bug in Build-Module ... line 243 is coming out false, so the manifest version does not get updated! 😳😬 https://github.com/PoshCode/ModuleBuilder/blob/fe0d0866866a21c281b855768dcf3010f355874e/Source/Public/Build-Module.ps1#L242-L249
Jaykul commented 6 months ago

The bug analysis:

It's using $Version when it should have used $ModuleInfo.Version

InitializeBuild and GetBuildInfo create a $ModuleInfo object that is the combination of the actual parameters passed to Build-Module and the defaults in build.psd1....

Because I wrote these long before the Get-ParameterValue function in the Configuration module, they do not set the variables they read from build.psd1 into the variable scope of Build-Module; they only update the $ModuleInfo object that is returned, so it's not safe for Build-Module to ever reference it's parameter variables directly -- it should always use the version that's set on $ModuleInfo ...

Oops.

My only excuse: most of us use GitVersion or something like that to dynamically set the version, so there are not currently any tests where that parameter is set in the build.psd1 instead of passing it in. 😳