Repository navigation
Adding powershell linter hook - best practice #2645
Copy link
Copy link
Open
Description
search you tried in the issue tracker
powershell, return code, exit code
describe your issue
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.
I added a hook config as
PowerShell/PSScriptAnalyzer@master...juju4:PSScriptAnalyzer:devel-precommit
- id: powershell_scriptanalyzer
name: Powershell lint with PSScriptAnalyzer
description: This runs PSScriptAnalyzer on your powershell files
entry: pre-commit powershell_scriptanalyzer
language: script
files: ^.*\.ps1$
types: [text]
entry: pwsh -Command "Invoke-ScriptAnalyzer -Settings PSGallery -Recurse -ReportSummary -EnableExit -Path ."
require_serial: false
additional_dependencies: []
minimum_pre_commit_version: '0'
pass_filenames: false
verbose: true
In the target repo, I added following config
- repo: https://github.com/juju4/PSScriptAnalyzer
rev: 4d6a4a36c78df215bc8fa637d05929eb7a9112d9
hooks:
- id: powershell_scriptanalyzer
entry: /usr/local/bin/pwsh -Command "Invoke-ScriptAnalyzer -Settings PSGallery -Recurse -ReportSummary -EnableExit -Path ."
3 minor issues as using entry to deal with them for now.
- As I'm executing on non-windows system, I have to customize/duplicate entry value with pwsh full path. not sure if better way?
- to support powershell cmdlet include/exclude rules or severity (https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md), I again have to customize entry. any way to define pre-commit fields to pass that inside the pwsh Command? default args apply outside.
- 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.
Else happy to take more comments
Thanks a lot for your work!
pre-commit --version
2.20.0
.pre-commit-config.yaml
repos:
- repo: https://github.com/juju4/PSScriptAnalyzer
rev: 4d6a4a36c78df215bc8fa637d05929eb7a9112d9
hooks:
- id: powershell_scriptanalyzer
entry: /usr/local/bin/pwsh -Command "Invoke-ScriptAnalyzer -Settings PSGallery -Recurse -ReportSummary -EnableExit -Path ."~/.cache/pre-commit/pre-commit.log (if present)
No response
Reacted by Mason Lin, nwsparks, Dave Tapley and Taylor Buchanan
Metadata
Metadata
Assignees
Labels
No labels
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?