PowerShell-RFC icon indicating copy to clipboard operation
PowerShell-RFC copied to clipboard

RFC0004-PowerShell-Module-Versioning

Open joeyaiello opened this issue 8 years ago • 55 comments

Use this issue to comment on this RFC: https://github.com/PowerShell/PowerShell-Language-RFC/blob/master/1-Draft/RFC0004-PowerShell-Module-Versioning.md

joeyaiello avatar Apr 27 '16 00:04 joeyaiello

Thank you for fixing the versioning. This looks great

pcgeek86 avatar Apr 27 '16 00:04 pcgeek86

:+1:

glennsarti avatar Apr 27 '16 01:04 glennsarti

First, I like the direction this is going. Semver is really nice for module/pkg level versioning.

RE Alternative 2 and the use of pre-release versioning suffixes, .NET "versions" are required just for strong named assemblies. This is true for NuGet .NET pkgs that contain strong named .NET assemblies as well. However NuGet allows the pkg version to be specified as a string in the nuspec file.

The only issue I see with PowerShell is that internally PowerShell must convert the ModuleVersion field of the manifest to a .NET Version. So what if you added a new field to the manifest such as ModuleSemVersion or some such thing? It wouldn't be the first time a field was added to the manifest (looking at you RootModule).

You would have to deal with the existing .NET versions vis-a-vie this new semantic version but that doesn't seem like it would be too hard. Modules that have published pkgs using .NET versions (say 1.0.0.0) would be required to be greater than their predecessors (1.0.1) when publishing an update using semver.

BTW watch out for using a prelease string like preview. The prerelease field is treated lexigraphically for determing which version is greater e.g.:

1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0

I would stick with recommendations of alpha, beta, rc to ensure proper update version checking.

rkeithhill avatar Apr 27 '16 02:04 rkeithhill

Yep, something in the PSData table could work to allow the semver pre-release stuff. If present, it overrides ModuleVersion when running Publish-Module. (Would probably be best to combine that with a 4-part version including build number in the ModuleVersion key, as a best practice, so different prereleases still have a unique ModuleVersion.)

dlwyatt avatar Apr 27 '16 03:04 dlwyatt

@dlwyatt I like being able to easily track what version of the module I use, all the way to the source code (not just release notes).

I experimented with including build number in a module version in https://github.com/PowerShell/platyPS After few releases, I tend to remove build number from the version.

  • Import-Module for particular version becomes harder. You need exact version, because wild-cards are not supported. So you need to query Get-Module -ListAvailable to see all versions before import (nobody is going to remember the build number).
  • Build numbers are somewhat arbitrary and are artifacts of the CI system, not the code itself.

For git repos git describe generates version purely from the source (and source history). That way is not tighted to a particular CI server and generates same version identifiers, when build on another machine uses the same commit. But it includes part of sha1 in a form of string.

Perhaps, including git describe output in a manifest in some field can be used for unique identifiers. And version can remain semver.

vors avatar Apr 27 '16 04:04 vors

Another possible way to deal with the preview versioning (for now) is that the -alpha is only used as a Gallery module version. Once the module is installed on the system, Import-Module, etc will use the numbered version without the preview suffix. Only the PowerShellGet module would use that information to ensure that the user doesn't install a preview module if they don't want one.

To add to @rkeithhill's point about having a separate module version field that includes the preview suffix, the .NET ecosystem solved this problem by using the AssemblyInformationalVersion for the full semantic version string. Some discussion on the 3 different version attributes for .NET assemblies here:

http://stackoverflow.com/questions/64602/what-are-differences-between-assemblyversion-assemblyfileversion-and-assemblyin

daviwil avatar Apr 27 '16 14:04 daviwil

Love that this is getting some traction. We can't get away from the "x" modules/resources fast enough.

I am in favor of alternative 2 - with @rkeithhill's caution about alpha, beta, rc vs preview.

I would also suggest that the *-package and PowershellGet cmdlets support a -prelease switch so that without that, results with prerelease versions are not accidentally installed. (Makes it intentional.)

The other caution as we move to more versions of modules available is that currently, module dependencies are either "latest" or a specific version. We should be able to specify a range of support, like everything less than major version two, or any minor version greater than 4 of the same major version. This capability makes it easier to allow for dependencies to rev without every contingent module needing to update.

@daviwil I'm not in favor of two different versions floating around - if I get different results from get-module as to what module is installed vs. what find-module/install-module use, that'll make supporting resources much more difficult - "Oh, you have THAT version number, I need the other one." Also, people have a hard enough time revving one version properly, much less two separate ones.

smurawski avatar Apr 27 '16 18:04 smurawski

@smurawski Good point, thanks!

daviwil avatar Apr 27 '16 18:04 daviwil

How about a separate field that only indicates eventual prerelease status? I.E. Only one version field, but a separated one for alfa, beta etc.

powercode avatar Apr 27 '16 20:04 powercode

Not a bad idea @powercode, but nuget already supports the prerelease field in versioning, so I say keep it simple and update the one thing.

smurawski avatar Apr 27 '16 20:04 smurawski

Doesn't semver already cover beta vs production-ready versioning?

0.Y.Z indicating pre-release and X.Y.Z (where X -ge 1) is production-ready.

Does .NET versioning preclude 0.Y.Z versions, or is the problem that it would require re-versioning for many existing pre-release modules?

michaeltlombardi avatar Apr 27 '16 22:04 michaeltlombardi

What about pre-release versions of non 1.0 software? Like a pre-release of the 2.0 version.

On Wed, Apr 27, 2016 at 5:46 PM, Michael T Lombardi < [email protected]> wrote:

Doesn't semver already cover beta vs production-ready versioning?

0.Y.Z indicating pre-release and X.Y.Z (where X -ge 1) is production-ready.

Does .NET versioning preclude 0.Y.Z versions, or is the problem that it would require re-versioning for many existing pre-release modules?

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/PowerShell/PowerShell-RFC/issues/10#issuecomment-215254323

https://powershellstation.com

MikeShepard avatar Apr 27 '16 22:04 MikeShepard

@michaeltlombardi Semver does cover pre-release vs production via the appended -<prelease-name> e.g. 1.0.0-alpha1. The .NET System.Version type precludes this because the last field (Revision) must be an integer. The basic issue is that modules use System.Version and that type has no accommodation for specifying that a release is a pre-release.

This is important for pkg management systems where you want to allow folks who want to install a "pre-release" to do so but they have to explicitly indicate they know they're getting a pre-release. As @smurawski says, there should be a -Prerelease switch on Find-Module, Install-Module, Get-InstalledModule, etc which would be required to even find/install/list prerelease modules. BTW this switch does exists on the Install-Package command for the NuGet Pkg Mgr console in Visual Studio. So perhaps there would be some transfer of learning for devs at least. :-)

Right now there is no concept of "segregating" prerelease modules from production modules on PSGallery AFAIK. This could be solved by adding another metadata field to the ModuleManifest but NuGet has solved this issue using semver. For that matter, PowerShellGet uses NuGet under the covers. Kind of makes sense to just roll with semver - if possible.

I was thinking before this would only impact the ModuleVersion in the manifest but there's more. There's the #Requires -Modules PSWorkflow, @{ModuleName="PSScheduledJob";ModuleVersion=1.0.0.0} which is a .NET Version (I believe) and the Import-Module -RequiredVersion/MinimumVersion parameters are of type Version. :-( Curiously MaximumVersion is of type string. So this makes it harder to use semver in the ModuleVersion. Although changing from Version to string (or a new SemVersion type) might work. It is sort of a "widening conversion" except for that fourth (Revision) field. Argh... Nothing's ever easy. :-(

@MikeShepard That would simply be 2.0.0-alpha1, 2.0.0-alpha2, 2.0.0-beta1, 2.0.0-rc1, etc.

rkeithhill avatar Apr 27 '16 23:04 rkeithhill

I was replying to @michaeltlombardi. :-)

MikeShepard avatar Apr 28 '16 00:04 MikeShepard

@MikeShepard Ah, missed that. Sorry.

rkeithhill avatar Apr 28 '16 00:04 rkeithhill

@rkeithhill: Okay, I think I understand now. We were looking at two different problem sets:

Generally Pre-Release Modules

Per SemVer, modules without a stable API (still changing/removing functions, non-fixed DSL, etc) would be versioned 0.Y.Z

Released Modules

Once a generally pre-release module has stabilized and is ready for first production release, it would bump to 1.Y.Z and increment Y and Z as necessary. The next time a change is made which breaks backward compatibility, 1 will increment to 2.

Pre-Release Versions of Current Updates

The above doesn't address the problem of people wanting to beta-test version 2.Y.Z of a module before the author/maintainer marks it as fit for production. Essentially, we're discussing adding a "not-fully-ready-yet" flag to modules when we're past 0.Y.Z but we want to make the current work-in-progress version available?

If that's the case, following strict semantic versioning and adding the PreRelease flag definitely makes the most sense.

Figuring out how to make it play nice with .NET versions and catch the second and third order effects sounds trickier.

Edit: Clarity, grammar.

michaeltlombardi avatar Apr 28 '16 01:04 michaeltlombardi

@michaeltlombardi

Essentially, we're discussing adding a "not-fully-ready-yet" flag to modules when we're past 0.Y.Z but we want to make the current work-in-progress version available?

Yup. As soon as you try to handle prerelease versions of a module with a convention like 0.Y.Z then it breaks down for prereleases of versions 1.1.0, 1.2.0, 2.0.0, etc.

One really, really cheesy convention that could handle future prereleases would be to make the range Major.Minor.Patch.0 - Major.Minor.Patch.999 be recognized as prerelease. Production would require -ge Major.Minor.Patch.1000.

OK now that I said that, I think I just threw up a little in mouth. Blech! Besides, that doesn't work with existing modules which have versions like 1.0.0.0. They would be flagged incorrectly as prerelease.

rkeithhill avatar Apr 28 '16 02:04 rkeithhill

I don't like any of the alternates

Pre-release of 2.0 should stay on GitHub, and after 1.0 only stable should be in the gallery.

BladeFireLight avatar Apr 28 '16 03:04 BladeFireLight

@bladefirelight The problem with that is it is harder to get folks to test. When you have it integrated into the package management process (with explicit intentions to get prerelease versions) you make it easier for people to try out newer version. Also, for people who want a particular bug fix that may not get shipped a real release for a while, pre-release packages can be a big helper.

I've seen projects where we had to depend on pre-release versions of components because it was taking too long to get the actual release shipped and the fixes in the pre-release were critical.

smurawski avatar Apr 28 '16 18:04 smurawski

I see your point, but if you willing to go beta in production (for good reason) then you should be competent enough to package a module from github.

It would be nice to have a flag for non-release. however the gallery does not support backwards numbering. so you cant patch a security release for 1.5.6 when you have published 1.9.99-beta5 with the same module name.

BladeFireLight avatar Apr 28 '16 19:04 BladeFireLight

That's a good point. We should be able to publish any version number we like. Separate issue, I suppose, but still related.

dlwyatt avatar Apr 28 '16 19:04 dlwyatt

@BladeFireLight

so you cant patch a security release for 1.5.6 when you have published 1.9.99-beta5 with the same module name.

Well that would be an issue the PSGallery would need to fix, if that's the case. Regardless of this "prerelease" issue you should be able to publish a patch to a previous version - say 1.5.7 when the latest is say 2.0.0? Just because there is a newer version, doesn't mean everybody can adopt it. Perhaps 1.5.7 supports PS 3 and 2.0.0 only supports PS 5.

rkeithhill avatar Apr 28 '16 20:04 rkeithhill

The PSGallery has in private communication said they will change that. No timeframe though.

powercode avatar Apr 28 '16 22:04 powercode

@bladefirelight It's not about competence, it's easy of adoption and discovery. I'll never go look for pre-release versions if I have to track down each github repo and look at tags or releases, but find-module -prerelease with some search criteria is much easier.

smurawski avatar Apr 28 '16 22:04 smurawski

so long as older versions of find-module are going to default to -prerelease:$false from the server's perspective, I'm fine with that approach.

BladeFireLight avatar Apr 29 '16 16:04 BladeFireLight

I concur with @rkeithhill and @smurawski that priority should be given to adoption and discovery, using the semver+pre-release flags/search capabilities: you want consumer feedback early, this needs easy and centralized discovery/update. It's easier to search and try new modules from gallery, rather than trying to use github as a _pre-release gallery _to discover and install modules. Github's amazing for collaboration, source sharing and so on, not so much as a PowerShell Gallery ;) @BladeFireLight has a good point with re-releasing any version you'd like to patch older version though! Can we get rid of the 'x' now?

gaelcolas avatar May 09 '16 14:05 gaelcolas

I definitely support using semver, kill the 'x' and 'c' and so on.

matthitchcock avatar May 09 '16 14:05 matthitchcock

I think there is consensus developing on the versioning approach ... great. But there is one aspect that the RFC or any of the comments don't talk about - the impact of dropping 'x' from the module name.

Consider xActiveDirectory module. In the 'drop the x' approach, it would become ActiveDirectory and on systems where these resources will be used, ActiveDirectory role will be turned on and there will be 2 version of this module:

  • One in System32 - owned by Active Directory team with AD cmdlets
  • Second in ProgramFiles - containing only DSC resources

I feel as part of this RFC (or maybe another RFC), we should also close on potential names for modules in 'drop the x' approach/world.

HemantMahawar avatar May 12 '16 00:05 HemantMahawar

@HemantMahawar Since this RFC is called "Module Naming and Versioning for PowerShell Gallery" I think this is the RFC for that discussion as opposed to another RFC.

In terms of simply removing the "x" I believe just naming the module to something that shares the same name will cause issues. For example, if I'm using xHyper-V and we rename it to "Hyper-V" we then have two different versions on the server - any other scripts I've written that use Import-Module Hyper-V will then have an ambiguous reference to a module name there.

There is also consideration to be given to the implied intent of the module based on its name as well. Take your example there - if both modules are called ActiveDirectory then it is unclear what each would do, and it wouldn't be unreasonable to expect that they are both the same in terms of functionality, but really one is to manage the product directly, and one to manage the DSC resources.

Based on that, I would propose that when we remove the "x" we look at a naming format that clearly identifies the modules as having DSC resources in them. For example, "xSharePoint" could become "SharePointDSC" as that clearly identifies that this is the module for DSC resources for SharePoint. There is an argument here that putting "DSC" in to the name means that you become limited to really just shipping DSC resources in the module, and not other scripts or components - I'm not aware of any other DSC resource modules currently that do this (that being said I've not used them all directly at this point either) but I would suggest that components that aren't related to the DSC resources can/should be delivered in a separate module anyway. I would be keen to know if anyone has a specific use case for this scenario though so we can apply the thinking to that.

BrianFarnhill avatar May 12 '16 01:05 BrianFarnhill

I'm generally not a fan of naming conventions. I spent many years in a big enterprise arguing with people who didn't use naming conventions correctly. It was a pointless waste of energy and I learned in the end that attributes and values, or metadata, were far better for identification of what resources were and what they did rather than names themselves. You can never enforce a naming convention and everyone has their own interpretation of it. While a Name is needed for everything, it is more for human readability and for us to interpret than anything else. Perhaps instead of focusing on and relying on naming we need to consider making it easier to add and display other information such as GUIDS and Tags. I haven't thought through how this would be implemented yet, but I think using "Import-DSCResource -ModuleGUID 'some guid' is probably more reliable than hoping someone hasn't overwritten the AD module or created a duplicate.

matthitchcock avatar May 12 '16 02:05 matthitchcock