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

Feature Request Support Versioning for Standalone Functions #11667

Closed
jdhitsolutions opened this issue Jan 23, 2020 · 60 comments
Closed

Feature Request Support Versioning for Standalone Functions #11667

jdhitsolutions opened this issue Jan 23, 2020 · 60 comments
Labels
Committee-Reviewed PS-Committee has reviewed this and made a decision Issue-Enhancement the issue is more of a feature request than a bug Resolution-Answered The question is answered.

Comments

@jdhitsolutions
Copy link
Collaborator

Summary of the new feature/enhancement

When using Get-Command the only time you see version information for a command is when it is part of a module with a manifest. And even then, I think the version is really for the module. There should be a way to support versioning on a per function level, especially for stand-alone files. I may have a single function command in a PS1 file. I'm happy to dot source and run the command. But I'd like to see a version number when I use Get-Command.

Proposed technical implementation details (optional)

The System.Management.Automation.FunctionInfo class has the necessary properties, but they are read-only. It would be nice to have a function equivalent to the PScriptInfo metadata that is used with PowerShellGet and published scripts. Let me have a metadata section that PowerShell will process and use when the function is imported into PowerShell.

@jdhitsolutions jdhitsolutions added the Issue-Enhancement the issue is more of a feature request than a bug label Jan 23, 2020
@iSazonov
Copy link
Collaborator

Please add info how you'd want to enhance PowerShell language to add the version. In cmdletbinding attribute?

@jdhitsolutions
Copy link
Collaborator Author

My thought was to do something like New-ScriptFileInfo which generates a comment header like this:


<#PSScriptInfo

.VERSION 1.0

.GUID 66c837b7-6478-4571-9dec-0621e13df4c3

.AUTHOR Jeff

.COMPANYNAME

.COPYRIGHT 2020

.TAGS

.LICENSEURI

.PROJECTURI

.ICONURI

.EXTERNALMODULEDEPENDENCIES 

.REQUIREDSCRIPTS

.EXTERNALSCRIPTDEPENDENCIES

.RELEASENOTES


.PRIVATEDATA

#>

<# 

.DESCRIPTION 
 This is a cool function 

#> 
Param()

Make it PSFunctionInfo and have Get-Command parse it. Or in the same way that PowerShell can parse #requires, have it parse #version. Where it gets tricky is when you have multiple functions in the same ps1 file, so anything I would do as a function author, would need to be enclosed in the function. This could be a parsed comment block, new cmdletbinding() option, or perhaps a whole new attribute.

Function Get-Awesomeness {

 [cmdletbinding()]
 [alias("awe")]
 [outputtype("psobject")]
 [version("1.1.0")]

 Param ()

 ...
}

@iSazonov
Copy link
Collaborator

I don't see a value from the feature. We can publish on PowerShellGet and distribute PowerShell scripts as only modules, we can not do this for files. Can you describe a business case/workflow?

@jdhitsolutions
Copy link
Collaborator Author

There are many people who create PowerShell solutions that are never published in the gallery. They are used internally, say in a corporate environment. And not everything is packaged into a module. I may work in a corporate environment and have a standalone script file with a function. I want the ability to keep track of the version for that function. If I run Get-Command Get-CompanyFoo, I need to be able to see a version number. For that matter, even in a module, all exported functions share the same version number. I'd like a facility to track version information on a per-function basis. And of course, without having to rely on reading the source code. If a help desk technician is using one of my functions, they need to be able to use PowerShell to discover the command version.

Certainly, not every function needs this, even those in a module. I have no problem with a function in a module using the module version if no command-specific version is detected.

@iSazonov
Copy link
Collaborator

@jdhitsolutions Thanks!

I see two component in your scenario - (1) a version tracking system, (2) a distribution system.
The first one could be GIT (others?).
It is not clear how you distribute script files.

(I am trying to understand where is right place for the requested attribute.)

@essentialexch
Copy link

I leave functions at clients on a regular basis, which are current as of the last time I used them at that particular client. One I used at a client today springs to mind - getWUlog. It knows how to connect to a remote system using both WinRM and psexec (it checks to see if 139 or 5985 are open) and retrieve the WindowsUpdate log from that computer, retrieve it to the local computer, and open notepad.

Another is getFrameworkVersion. Does just that - looks to find the .NET Framework version installed on a given computer, using either CIM or the remote registry service (again - checks ports to figure out what to do), reports those, and reports on what versions are blocked, if any.

These are standalone functions. Not part of a module. But they have gone through regular updates over the last few years.

It would be great to attach a version to each of them. Right now, I just have a "last modified date" at the top of the source. Not as useful...

@jdhitsolutions
Copy link
Collaborator Author

Distribution is irrelevant in my mind to this discussion. And yes, git plays a role but isn't the issue. If I am in PowerShell and am using a standalone function. When I run Get-Command Get-Foo I want to see the version number of the function. It is as simple as that. It doesn't matter how the function got distributed. Give me a way to inject metadata into the function.

@jdhitsolutions
Copy link
Collaborator Author

And to be absolutely clear, I don't want to force a user, or even myself, to track down the source and look for comments or notes.

@lanwench
Copy link

lanwench commented Jan 24, 2020

I definitely write/use some standalone functions, but most are in modules. And most of those are random flotsam tools that can be used as standalone functions. I always put semantic versions and changelogs in .NOTES within the comment block, and a [version]$Version in the begin block, because I want to keep track of what changes I made to a particular function, not just to the module (which I increment when I make changes to the inner functions). Having something like [version()] or [cmdletbinding(Version='01.00.0000')] would be spectacular; I like it better than .VERSION because I know a lot of people put multiple functions into a psm1 file (although I don't).
I use git, also, btw, but I don't commit every time I make a change to an individual function; I bundle them up and commit when I change the module, usually w the module version as the commit message. Yeah, yeah, I know, I'm weird.

@SteveL-MSFT
Copy link
Member

If the script is found in $env:PATH, it does show up for Get-Command. So it seems reasonable to map the existing ScriptFileInfo metadata to the ExternalScriptInfo members which includes the Version.

@SteveL-MSFT SteveL-MSFT added Hacktoberfest Potential candidate to participate in Hacktoberfest Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors labels Jan 24, 2020
@jdhitsolutions
Copy link
Collaborator Author

Be careful with that assumption Steve. I might have a single ps1 file with multiple functions. I don't want to trust that Get-Command can find the script file. Heck, I might want to define a versioned function in a PowerShell profile script.

@essentialexch
Copy link

Definitely have versioned functions in my profile script.

@jdhitsolutions
Copy link
Collaborator Author

We already have the System.Management.Automation.FunctionInfo type which has a Version property. We need a way so that when the function is loaded, the version property is populated from metadata in the function.

@iSazonov
Copy link
Collaborator

Thanks all for great feedback! I have still some questions. What behavior you expect if PowerShell found some functions with same name? Run function with higher version? Should we take into account scopes (you load in current scope old function - should we call more new function from global scope)? Or we want to have only informational attribute?

@jdhitsolutions
Copy link
Collaborator Author

This isn't about running or distributing functions. All I'd like is a mechanism to provide a way to track and discover version information so that if I run Get-Command, or perhaps a new command like Get-Function, I can see some metadata about the function. I have some ideas that I might try to prototype through PowerShell scripting.

@essentialexch
Copy link

Thanks all for great feedback! I have still some questions. What behavior you expect if PowerShell found some functions with same name? Run function with higher version? Should we take into account scopes (you load in current scope old function - should we call more new function from global scope)? Or we want to have only informational attribute?

I don't think anyone has suggested any change in the way PS executes functions. We just want to put a version on them. Informational and a way to interrogate same.

@iSazonov
Copy link
Collaborator

Thanks! Next question I have. A file with some functions could have a version attribute common for all functions in the file. Should we consider this?

@iSazonov
Copy link
Collaborator

I have some ideas that I might try to prototype through PowerShell scripting.

You could share the ideas in gist.

@jdhitsolutions
Copy link
Collaborator Author

That's my plan.

@iSazonov
Copy link
Collaborator

Should it be classic Version or SymVer 2.0?

@doctordns
Copy link
Contributor

doctordns commented Jan 26, 2020

I am becoming increasingly convinced function versioning is a good thing.

To answer @iSazonov latest question - if we are to have it, why NOT use SymVer?

And regarding a file of functions - I'd argue that the attribute is per function with no per-file attributes. Much like today's CMDLETBinding works.

@iSazonov
Copy link
Collaborator

iSazonov commented Jan 26, 2020

Prototype is pulled in ##11686

You can download an artifact from the PR and play with new attribute.

@doctordns
Copy link
Contributor

doctordns commented Jan 26, 2020

Sweet.

Thinking about it - why not extend the PSVersionAttribute to include the version of the script. If we version modules and (hopefully now!) functions, why not scripts?

The PSVersionAttribute could also serve as a default value for functions defined in the script.

And before anyone else asks... Can function execution be versioned?

We could load multiple versions of a function, execute the latest by default, but have a -PSFunctionVersion common parameter that says which specific version to run.
No doubt there are more alternatives - but should we provide versioned function execution?

@vexx32
Copy link
Collaborator

vexx32 commented Jan 27, 2020

If it's an attribute you could always just reuse it, much like how [CmdletBinding()] can be applied to both functions and scripts, you could always just use [PSVersion()] for both functions and scripts. This is looking like an interesting approach. 🙂

I don't foresee a lot of use of this kind of thing in modules, where we already have versioned code for the most part, but for standalone scripts and functions this could be very interesting indeed 🙂

@doctordns
Copy link
Contributor

This isn't about running or distributing functions. All I'd like is a mechanism to provide a way to track and discover version information so that if I run Get-Command, or perhaps a new command like Get-Function, I can see some metadata about the function. I have some ideas that I might try to prototype through PowerShell scripting.

If we are to add function versioning, why limit it to purely documentation? If I can specify and query function versions, wouldn't it be sensible to allow execution based on version number?

Either a way to load multiple versions of a function and be able to pick the one to execute, or enable the user to choose amongst different versions to load into the function list we see with gcm and then execute that one.

@jdhitsolutions
Copy link
Collaborator Author

jdhitsolutions commented Jan 27, 2020

So here's a proof of concept I worked up based on the ScriptFileInfo commands:
https://gist.github.com/jdhitsolutions/65070cd51b5cfb572bc6375f67bcbc3d

What I'm really trying to model or prototype is the experience. I'd rather have the data exposed with Get-Command, because there is already an appropriate type.

image

And getting a mix of files.
image

If a function belongs to a module, I'm not going to bother with command versioning. That should be handled by the module.

Gist
A proof of concept to add and get PowerShell meta data information - PSFunctionInfo.format.ps1xml

@jdhitsolutions
Copy link
Collaborator Author

Don't overthink this or make it more complicated than it needs to be. Functions shipped with modules belong to the module. Full stop. That should be the recommended best practice. However, not every function that might be used in production is deployed with a module. I don't actually care about how it is deployed. All I'm saying is that I want a way to look at a loaded function in the Function: PSDrive and be able to see a version number, and perhaps some other metadata information. I don't want to force myself or an end-user to track down the source code or folder to discover version information.

I was hoping Get-Command would be the tool to gather this information, but perhaps this needs to be spun off into something completely separate for stand-alone function management.

@jdhitsolutions
Copy link
Collaborator Author

And maybe the answer is that this problem is best left to the community to solve. In which case, I think I have a good start on a solution.

@kilasuit
Copy link
Collaborator

Honest truth here is that dot sourcing functions is not the correct way to go, and should not have been recommended all those years back when the module system came in v2. The only time it was remotely sensible for use was in v1.

As we all know now, all functions should realistically be placed within a module, even those that you are loading as part of your profile (which you should load the module containing these functions) or using as part of a larger script for easier maintenance, or even those singular functions that you need to use in xyz scripts.

I can only see this change would add more confusion to those coming to the language than benefit by adding the suggested [Version] attribute to function definitions with many thinking that they would be required to set Module and Function versions when they are doing things properly and actually building modules of reusable code.

Yes this means you have to have a psd1 and a psm1 but 2 files for proper discoverability and maintainability isn't a huge ask to manage really

As you may tell, I personally disagree with this change & think there are better things to be focused on instead

@essentialexch
Copy link

Yes this means you have to have a psd1 and a psm1 but 2 files for proper discoverability and maintainability isn't a huge ask to manage really

Yes, it is a huge ask. Trying to make admin scripters into developers raises significantly the barrier to entry.

Saying "oh you have to copy this here and copy that there and then import it" is far more complicated and far more prone to error than saying "copy-and-paste this into a file named run.ps1 and then type ,\run.ps1".

This is a minor change and it stands to benefit casual/admin scripters far more than ternary operators or null-coalescing (which I still don't understand) or lots of other recent changes that were made for those of you who are devs. As was said about those, I can say about function versions: if you don't like it, don't use it.

@iSazonov
Copy link
Collaborator

@SteveL-MSFT I belive PowerShell committee could look the request to support versions for scripts and standalone functions. Prototype is in #11686.

@lanwench
Copy link

Honest truth here is that dot sourcing functions is not the correct way to go,

But people do it, and it isn't the only use case for this request anyway.

and should not have been recommended all those years back when the module system came in v2. The only time it was remotely sensible for use was in v1.

As we all know now, all functions should realistically be placed within a module, even those that you are loading as part of your profile (which you should load the module containing these functions) or using as part of a larger script for easier maintenance, or even those singular functions that you need to use in xyz scripts.

I can only see this change would add more confusion to those coming to the language than benefit by adding the suggested [Version] attribute to function definitions with many thinking that they would be required to set Module and Function versions when they are doing things properly and actually building modules of reusable code.

Yes this means you have to have a psd1 and a psm1 but 2 files for proper discoverability and maintainability isn't a huge ask to manage really

Yes, but this isn't relevant. Nobody is arguing that we shouldn't version modules. ;-)

As you may tell, I personally disagree with this change & think there are better things to be focused on instead

You wouldn't be required to use it. You aren't actually forced to use [CmdletBinding()] or parameter sets, either.
Commands, and cmdlets, have versions.
If a function itself has a version, whether or not said function resides within a module, it's simply a minor, but useful, documentation point. I have created numerous modules with varied and unrelated tools in them that don't justify their own individual modules. If my module is MiscStuff 1.1.0002, that's great for the distribution part; I use that. If there are thirty functions inside it and I want to quickly note whether I'm using Do-Thing 7.9.0 and be able to correlate it to an item in my changelog (which I do!), I would like some formal method for doing this, which would be in no way required by those who don't wish to.

@SteveL-MSFT SteveL-MSFT added Review - Committee The PR/Issue needs a review from the PowerShell Committee and removed Hacktoberfest Potential candidate to participate in Hacktoberfest Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors labels May 27, 2020
@SteveL-MSFT
Copy link
Member

@PowerShell/powershell-committee reviewed this, we believe the proper solution to have versioning for script functions is to wrap them in a module. It also not clear what the expected behavior would be if the script function is within a module, but has its own version attribute. Then there is concern about other parts of PowerShell, PowerShellGet, and PSGallery that would need to be updated to respect this new attribute. If the desire is to be able to pass around a single script file vs a folder (module), then it would be better to invest in the ability to import a zip/nupkg module directly and easier to turn a .ps1 into a module.

@SteveL-MSFT SteveL-MSFT added Committee-Reviewed PS-Committee has reviewed this and made a decision and removed Review - Committee The PR/Issue needs a review from the PowerShell Committee labels May 27, 2020
@essentialexch
Copy link

As an admin scripter and not a developer, I don't think that #7259 and this request (#11667) have anything to do with each other.

As an admin scripter I WILL NOT learn how to use modules. It's not relevant to me. It provides me NO VALUE. It's overhead FOR DEVELOPERS. Modules are a non-starter. (Not just for me, but most admin-scripters.)

For admin scripters and not developers - how does the committee suggest that versioning for functions/filters be done?

@vexx32
Copy link
Collaborator

vexx32 commented May 27, 2020

Not to be contrarian, but... versioning itself is a developer concept, by and large. I'm not sure why you're trying to draw this line here, of all possible places. 😕

@essentialexch
Copy link

Because I've released dozens of standalone functions and scripts. Without modules. Pretty sure this is covered above in prior comments from me, and several other popular bloggers/publishers.

@SeeminglyScience
Copy link
Collaborator

I don't think that #7259 and this request (#11667) have anything to do with each other.

Yeah I don't really get the connection either to be honest.

I WILL NOT learn how to use modules.

FWIW you just change the extension to psm1 and (optionally) run New-ModuleManifest. There's not a whole lot to it.

It's not relevant to me. It provides me NO VALUE.

If you're publishing something for others to consume it definitely provides value. The way scopes work for modules make it a lot harder to step on someone's global session state and vice versa. That makes your function significantly more resilient to unexpected differences in environments.

It's also way easier to consume. If you release a function as a script folks need to dot source, they need to know where it is, dot source it, then use the command. If you release it as a module, folks can just deploy it ahead of time and call it whenever they want.

how does the committee suggest that versioning for functions/filters be done?

If versioning was implemented for individual functions, would you expect their version to be queryable?

If yes, can you elaborate a little bit on what scenario you would expect the user to query it? Would you expect it to play into any other systems like #requires tags?

If it would just be metadata visible in the source then you could just put it in the NOTES section of comment based help.

@iSazonov
Copy link
Collaborator

iSazonov commented May 28, 2020

Based on PowerShell Committee conclusion I close the issue (stop tracking) but you free to continue the discussion.

@iSazonov iSazonov added the Resolution-Answered The question is answered. label May 28, 2020
@essentialexch
Copy link

Yes, I use the NOTES section today and a $pVersion/$pName. I suspect most of us with the need, do that.

When I was writing "I will not" I was speaking of the generic person, not of me specifically (although I fall into that category).

@SeeminglyScience
Copy link
Collaborator

and a $pVersion/$pName

What do you do with those? Do you have an example of a loose function you've published? That may help in understanding the use case.

When I was writing "I will not" I was speaking of the generic person, not of me specifically (although I fall into that category).

Yeah there are definitely people who refuse to learn about modules. I have known and currently know plenty of folks like that (and have been said folk a few years ago), no arguments that they exist. That said, the overlap between those folks, and those who 1. care about versioning and 2. have any desire to publish their work - in my experience is almost zero. Realistically most of the folks who check boxes 1 and 2 will take the ~10 minutes to google how to wrap in a module real quick before they publish. Or more often, they don't care about versioning and they'll just slam it in a gist or a blog post.

@lanwench
Copy link

and a $pVersion/$pName

What do you do with those? Do you have an example of a loose function you've published? That may help in understanding the use case.

When I was writing "I will not" I was speaking of the generic person, not of me specifically (although I fall into that category).

Yeah there are definitely people who refuse to learn about modules. I have known and currently know plenty of folks like that (and have been said folk a few years ago), no arguments that they exist. That said, the overlap between those folks, and those who 1. care about versioning and 2. have any desire to publish their work - in my experience is almost zero. Realistically most of the folks who check boxes 1 and 2 will take the ~10 minutes to google how to wrap in a module real quick before they publish. Or more often, they don't care about versioning and they'll just slam it in a gist or a blog post.

I know how to use modules. I write them all the time. Heck, these functions are inside modules a lot of the time, and I use internal versioning so I can keep track of what last changed in a function without having to pull out to an external (to the function) changelog. I don't see why .VERSION in a function would interfere with a module version. I just don't.

@SeeminglyScience
Copy link
Collaborator

I know how to use modules. I write them all the time. Heck, these functions are inside modules a lot of the time, and I use internal versioning so I can keep track of what last changed in a function without having to pull out to an external (to the function) changelog. I don't see why .VERSION in a function would interfere with a module version. I just don't.

Right but the main thing is: what are you going to do with that metadata? Is it just something you look at in the source of the function? If so, can you elaborate on how the .NOTES section isn't suitable for that?

Also this issue was for allowing a standalone function to declare it's version number in Get-Command output. A request to include a full change log would be a pretty different implementation and probably better off in it's own issue.

@essentialexch
Copy link

essentialexch commented Aug 10, 2020

that's easy to answer. that means i have to open it in an editor or perform some type of awkward string search to find out the version installed on a given computer/given location on said computer. that isn't always easy as this answer. :-)

@vexx32
Copy link
Collaborator

vexx32 commented Aug 10, 2020

Not really?

Notes field shows in the Get-Help output if you're writing it as proper comment-based help (which you should be anyway).

function test {
    <#
    .NOTES
    Version: 1.5.0
    #>
    [CmdletBinding()]
    param()
}

Get-Help test -Full

# or
Get-Help test | % alertSet

Result:

PS> Get-Help test -Full
SYNTAX
    test [<CommonParameters>]


DESCRIPTION


PARAMETERS
    <CommonParameters>
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer, PipelineVariable, and OutVariable. For more information, see
        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).

INPUTS

OUTPUTS

NOTES


        Version: 1.5.1


RELATED LINKS

PS> get-help test | % alertset



    Version: 1.5.1

@essentialexch
Copy link

So? I'm not impressed. There were other, more verbose ways to do ternary operators too. And yet... a more compact way got implemented. Because (a part of) the community wanted it. I still don't know what the heck null-coalescing operators are.

@vexx32
Copy link
Collaborator

vexx32 commented Aug 10, 2020

Not really sure what you're after, then. That quite clearly lets you do what you're after relatively easily. I don't see it being worth the time to add extra fields there.

If you do, feel free to open a PR and we'll talk about it further. 🤷

@essentialexch
Copy link

A PR for what? I'm not a C# coder. I haven't been a professional developer for over 30 years.

I think several of us were really clear about what we are after, and our use cases, and saw those concerns minimized, as you just did again.

Those of you who are beyond admin scripting think "just make it a module". Most admin scripters aren't going to know how and they'll say (and I'll agree) that it's too much trouble once they see the requirements.

But this is pointless and I knew better. The PowerShell Committee conclusion was already reached. Sorry I commented.

@iSazonov
Copy link
Collaborator

The PowerShell Committee conclusion was already reached.

Any by-design conclusions can be reconsidered based on feedbacks.

@SeeminglyScience
Copy link
Collaborator

I think several of us were really clear about what we are after, and our use cases, and saw those concerns minimized, as you just did again.

I've been trying really hard to get to the bottom of what the actual goal and use cases are and my questions have been mostly ignored. I'd really like to understand.

Those of you who are beyond admin scripting

Man, I'm a sysadmin. Most of my career was spent thinking the hashtable syntax was "the splatting syntax". Most of my coworkers only know the absolute basics of PowerShell (if at all), same with most of the people I help on discord/reddit.

I get that you have some beef with the PS dev team, but please don't pretend like I couldn't possibly understand your perspective because I happen to know C# now. I'm constantly fighting for that perspective on this repo.

think "just make it a module". Most admin scripters aren't going to know how and they'll say (and I'll agree) that it's too much trouble once they see the requirements.

For anyone who comes across this thread later and gets discouraged from making a module, here are the requirements:

  1. Rename your .ps1 file to .psm1
  2. Use Import-Module ./file.psm1 instead of . ./file.ps1

That's it, you got a module. Everything else is just best practices you don't need to worry about yet. If you want to version it you need a manifest, here's the full requirements for that:

  1. Rename your .ps1 file to .psm1
  2. Run New-ModuleManifest -RootModule ./file.psm1 -Path ./file.psd1 -ModuleVersion 1.0.0
  3. Use Import-Module ./file.psd1 instead of . ./file.ps1

If you're shipping a loose function in a ps1 that the consumer (or yourself) would need to dot source, just throw it in a module real quick it'll make your life easier.

If you're shipping a directly invokable script, you can use New-ScriptFileInfo which will generate a script file with a comment like this:

<#PSScriptInfo

.VERSION 1.0.0

.GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

.AUTHOR username

.COMPANYNAME

.COPYRIGHT

.TAGS

.LICENSEURI

.PROJECTURI

.ICONURI

.EXTERNALMODULEDEPENDENCIES 

.REQUIREDSCRIPTS

.EXTERNALSCRIPTDEPENDENCIES

.RELEASENOTES


.PRIVATEDATA

#>

<# 
.DESCRIPTION 
     Quick script description here.
#> 
param()

And you can query that with Test-ScriptFileInfo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committee-Reviewed PS-Committee has reviewed this and made a decision Issue-Enhancement the issue is more of a feature request than a bug Resolution-Answered The question is answered.
Projects
None yet
Development

No branches or pull requests

10 participants