You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Adding powershell linter hook - best practice #2645
I'm working on a repository containing powershell scripts.
I have a pre-commit already enabled for other checks and I want to add powershell linting with https://github.com/PowerShell/PSScriptAnalyzer.
same problem applies if want pass_filenames=true. /usr/local/bin/pwsh -Command "Invoke-ScriptAnalyzer -Settings PSGallery -Recurse -ReportSummary -EnableExit -Path $@" did not work in my tests.
you shouldn't need a full path to pwsh -- it will look up on path automatically
pass_filenames: true is the recommended way to set up hooks -- otherwise you don't really benefit from pre-commit's file matching at all and then have to re-implement it using the tool.
I think what you actually want is to use language: dotnet which will build the executables which you'll call directly without using pwsh at all
which should be valid unless language can't be overriden but behavior below shown it applies
full output
% pre-commit run -a powershell_scriptanalyzer
[INFO] Installing environment for https://github.com/juju4/PSScriptAnalyzer.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/bin/bash', '/usr/local/bin/dotnet', 'pack', '--configuration', 'Release', '--output', 'pre-commit-build')
return code: 145
expected return code: 0
stdout:
7.0.100 [/usr/local/Cellar/dotnet/7.0.100/libexec/sdk]
stderr:
The command could not be loaded, possibly because:
* You intended to execute a .NET application:
The application 'pack' does not exist.
* You intended to execute a .NET SDK command:
A compatible .NET SDK was not found.
Requested SDK version: 3.1.424
global.json file: /Users/USERNAME/.cache/pre-commit/repo8rpcf_st/global.json
Installed SDKs:
Install the [3.1.424] .NET SDK or update [/Users/USERNAME/.cache/pre-commit/repo8rpcf_st/global.json] to match an installed SDK.
Learn about SDK resolution:
https://aka.ms/dotnet/sdk-not-found
yeah that output would say it's not a dotnettool so maybe language: dotnet isn't going to work for it -- is there a way to install powershell commandlets in a specific directory? if so then potentially a language: powershell could be added to pre-commit for direct language support
This seems reasonable to expect of a linter. I understand that this may be out of scope for a generalized tool as the analyzer seems to be, but does everyone really hand-roll this much in PS when they try to use this in real life?
Anyway, I realize that what I should actually be doing is taking a list of files provided by pre-commit, but I am pretty new to PowerShell, so I focused on getting the proof of concept part of making it useful. Seems the PowerShell people have had a ticket open regarding more control over what files it includes/excludes for a while now? Maybe I'm not getting something and this is much simpler to accomplish?
I think it should be possible to do this the "correct" way, but I have a few concerns:
I could be processing each file provided by pre-commit with a new invocation of ScriptAnalyzer and then aggregate the results before reporting and panicking, but I suspect this could be quite slow. Scripts running sandwiches of PS, git bash and Python seem slow enough on Windows, but on Linux - even more so. Probably fine to stick to just running it on the whole repo and then selecting the relevant files?
I guess most pre-commit scripts install their own prereqs? In this case, this might be tricky if you are not on Windows. I run this just fine on Linux with PS installed via snapd, but getting CircleCI to do it on a Ubuntu image was enough of a PITA to make me set up the CI to just do all the checks on a windows image. Would docker be the correct approach to making this truly portable? Does one then assume docker is available on windows machines?
is there a reasonable way to forward some of the lower level parameters Analyzer expects (like severity threshold) from pre-commit invocation? Or do we need an additional config file?
I'm new to this. I might still tough up and try to make this a generalized hook in a new repo. Anyone inspired to collaborate?
Activity
asottile commentedon Dec 17, 2022
you shouldn't need a full path to
pwsh-- it will look up on path automaticallypass_filenames: trueis the recommended way to set up hooks -- otherwise you don't really benefit from pre-commit's file matching at all and then have to re-implement it using the tool.I think what you actually want is to use
language: dotnetwhich will build the executables which you'll call directly without usingpwshat alljuju4 commentedon Dec 17, 2022
If I don't pass the full path for pwsh, I get
ok for pass_filenames true but how?
if using $@ and pass_filenames true, I get
on dotnet, not sure how, https://github.com/PowerShell/PSScriptAnalyzer is not a dotnet app.
from quick check, dotnet fails saying missing application pack.
asottile commentedon Dec 17, 2022
that's because you've incorrectly set
language: scriptwhich is to be used for scriptsjuju4 commentedon Dec 18, 2022
I tested locally with following pre-commit-config
which should be valid unless language can't be overriden but behavior below shown it applies
full output
asottile commentedon Dec 21, 2022
yeah that output would say it's not a
dotnettoolso maybelanguage: dotnetisn't going to work for it -- is there a way to install powershell commandlets in a specific directory? if so then potentially alanguage: powershellcould be added to pre-commit for direct language supportjuju4 commentedon Dec 22, 2022
As requirement for above to work (local or remote repo), I needed pwsh to be present and do
Install-Module -Name PSScriptAnalyzeras per https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/overview?view=ps-modules#installing-psscriptanalyzerAfter that, you don't need any path to call it from powershell.
I don't think that there is an option to directly call a powershell cmdlet from a non-powershell shell.
Or maybe through a wrapper script
"&" syntax may be possible from https://stackoverflow.com/questions/932291/calling-powershell-cmdlets-from-windows-batch-file
https://social.technet.microsoft.com/Forums/exchange/en-US/25e23957-d81b-468b-a683-90b6b84ed16b/calling-powershell-cmdlets-from-cmd-prompt
https://community.spiceworks.com/topic/1951541-running-a-powershell-function-from-command-line
If want to install cmdlet in a dedicated pre-commit path:
Install-Module only has a scope option (CurrentUser or AllUsers) - https://learn.microsoft.com/en-us/powershell/module/powershellget/install-module?view=powershell-7.3
It may be possible to use PSModulePath environment variable to alter install path - https://learn.microsoft.com/en-us/powershell/scripting/developer/module/installing-a-powershell-module?view=powershell-7.3
more testing needed.
asottile commentedon Jan 1, 2023
yeah I think the way to make this work nicely with pre-commit would be to build into a path and use
PSModulePathjuju4 commentedon Jan 8, 2023
Sadly install part does not seem to work directly from my testing
also same reported here
https://stackoverflow.com/questions/42488323/how-to-install-module-into-custom-directory
And match the absence of a prefix option for Install-Module
https://learn.microsoft.com/en-us/powershell/module/powershellget/install-module?view=powershell-7.3
https://github.com/PowerShell/PowerShellGet/issues/524
Seems the only option would be download and copy files manually
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_modules?view=powershell-7.3#how-to-install-a-module
quick try that seems to work
Where should this configuration go?
Also the current need for a full pwsh path is annoying, especially if running pre-commit both client and server side where path may be different.
asottile commentedon Jan 8, 2023
yeah the default
Install-Modulewon't do that, but if you build and install directly you should have full control over where the thing gets installedmartukas commentedon Apr 11, 2023
I have been trying to accomplish something similar. Took some lessons from this thread. I have an adhoc implementation in my dotfiles repo:
Basically, the wrapper/hook does the following:
This seems reasonable to expect of a linter. I understand that this may be out of scope for a generalized tool as the analyzer seems to be, but does everyone really hand-roll this much in PS when they try to use this in real life?
Anyway, I realize that what I should actually be doing is taking a list of files provided by pre-commit, but I am pretty new to PowerShell, so I focused on getting the proof of concept part of making it useful. Seems the PowerShell people have had a ticket open regarding more control over what files it includes/excludes for a while now? Maybe I'm not getting something and this is much simpler to accomplish?
I think it should be possible to do this the "correct" way, but I have a few concerns:
I'm new to this. I might still tough up and try to make this a generalized hook in a new repo. Anyone inspired to collaborate?
leandroscardua commentedon Nov 27, 2024
Hello Team,
Do we have any update on this issue? or other way to do it?