Skip to content

Commit

Permalink
Add PowerShell formatter linter (#2176)
Browse files Browse the repository at this point in the history
* Add PowerShell formatter linter

* Use -Raw parameter

* Run build.sh

* Fix tests

- Add test_folder parameter
- Refactor test files
- Create no_test_failure file

* Insert new line
  • Loading branch information
bdovaz authored Dec 26, 2022
1 parent 5512d9c commit 2eb9c7d
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 7 deletions.
117 changes: 117 additions & 0 deletions .automation/generated/linter-helps.json
Original file line number Diff line number Diff line change
Expand Up @@ -4084,6 +4084,123 @@
" prepend the command parameters with a hyphen (-), not a forward slash (/).",
""
],
"powershell_formatter": [
"",
"PowerShell[.exe] [-PSConsoleFile <file> | -Version <version>]",
" [-NoLogo] [-NoExit] [-Sta] [-Mta] [-NoProfile] [-NonInteractive]",
" [-InputFormat {Text | XML}] [-OutputFormat {Text | XML}]",
" [-WindowStyle <style>] [-EncodedCommand <Base64EncodedCommand>]",
" [-ConfigurationName <string>]",
" [-File <filePath> <args>] [-ExecutionPolicy <ExecutionPolicy>]",
" [-Command { - | <script-block> [-args <arg-array>]",
" | <string> [<CommandParameters>] } ]",
"",
"PowerShell[.exe] -Help | -? | /?",
"",
"-PSConsoleFile",
" Loads the specified Windows PowerShell console file. To create a console",
" file, use Export-Console in Windows PowerShell.",
"",
"-Version",
" Starts the specified version of Windows PowerShell.",
" Enter a version number with the parameter, such as \"-version 2.0\".",
"",
"-NoLogo",
" Hides the copyright banner at startup.",
"",
"-NoExit",
" Does not exit after running startup commands.",
"",
"-Sta",
" Starts the shell using a single-threaded apartment.",
" Single-threaded apartment (STA) is the default.",
"",
"-Mta",
" Start the shell using a multithreaded apartment.",
"",
"-NoProfile",
" Does not load the Windows PowerShell profile.",
"",
"-NonInteractive",
" Does not present an interactive prompt to the user.",
"",
"-InputFormat",
" Describes the format of data sent to Windows PowerShell. Valid values are",
" \"Text\" (text strings) or \"XML\" (serialized CLIXML format).",
"",
"-OutputFormat",
" Determines how output from Windows PowerShell is formatted. Valid values",
" are \"Text\" (text strings) or \"XML\" (serialized CLIXML format).",
"",
"-WindowStyle",
" Sets the window style to Normal, Minimized, Maximized or Hidden.",
"",
"-EncodedCommand",
" Accepts a base-64-encoded string version of a command. Use this parameter",
" to submit commands to Windows PowerShell that require complex quotation",
" marks or curly braces.",
"",
"-ConfigurationName",
" Specifies a configuration endpoint in which Windows PowerShell is run.",
" This can be any endpoint registered on the local machine including the",
" default Windows PowerShell remoting endpoints or a custom endpoint having",
" specific user role capabilities.",
"",
"-File",
" Runs the specified script in the local scope (\"dot-sourced\"), so that the",
" functions and variables that the script creates are available in the",
" current session. Enter the script file path and any parameters.",
" File must be the last parameter in the command, because all characters",
" typed after the File parameter name are interpreted",
" as the script file path followed by the script parameters.",
"",
"-ExecutionPolicy",
" Sets the default execution policy for the current session and saves it",
" in the $env:PSExecutionPolicyPreference environment variable.",
" This parameter does not change the Windows PowerShell execution policy",
" that is set in the registry.",
"",
"-Command",
" Executes the specified commands (and any parameters) as though they were",
" typed at the Windows PowerShell command prompt, and then exits, unless",
" NoExit is specified. The value of Command can be \"-\", a string. or a",
" script block.",
"",
" If the value of Command is \"-\", the command text is read from standard",
" input.",
"",
" If the value of Command is a script block, the script block must be enclosed",
" in braces ({}). You can specify a script block only when running PowerShell.exe",
" in Windows PowerShell. The results of the script block are returned to the",
" parent shell as deserialized XML objects, not live objects.",
"",
" If the value of Command is a string, Command must be the last parameter",
" in the command , because any characters typed after the command are",
" interpreted as the command arguments.",
"",
" To write a string that runs a Windows PowerShell command, use the format:",
" \"& {<command>}\"",
" where the quotation marks indicate a string and the invoke operator (&)",
" causes the command to be executed.",
"",
"-Help, -?, /?",
" Shows this message. If you are typing a PowerShell.exe command in Windows",
" PowerShell, prepend the command parameters with a hyphen (-), not a forward",
" slash (/). You can use either a hyphen or forward slash in Cmd.exe.",
"",
"EXAMPLES",
" PowerShell -PSConsoleFile SqlSnapIn.Psc1",
" PowerShell -version 2.0 -NoLogo -InputFormat text -OutputFormat XML",
" PowerShell -ConfigurationName AdminRoles",
" PowerShell -Command {Get-EventLog -LogName security}",
" PowerShell -Command \"& {Get-EventLog -LogName security}\"",
"",
" # To use the -EncodedCommand parameter:",
" $command = 'dir \"c:\\program files\" '",
" $bytes = [System.Text.Encoding]::Unicode.GetBytes($command)",
" $encodedCommand = [Convert]::ToBase64String($bytes)",
" powershell.exe -encodedCommand $encodedCommand"
],
"prettier": [
"Usage: prettier [options] [file/dir/glob ...]",
"",
Expand Down
5 changes: 5 additions & 0 deletions .automation/generated/linter-links-previews.json
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@
"image": "https://repository-images.githubusercontent.com/33149177/18c68000-a5b0-11e9-9d88-c03ff0e21635",
"title": "PowerShell/PSScriptAnalyzer"
},
"powershell_formatter": {
"description": "Download ScriptAnalyzer from PowerShellGallery. Contribute to PowerShell/PSScriptAnalyzer development by creating an account on GitHub.",
"image": "https://repository-images.githubusercontent.com/33149177/18c68000-a5b0-11e9-9d88-c03ff0e21635",
"title": "GitHub - PowerShell/PSScriptAnalyzer: Download ScriptAnalyzer from PowerShellGallery"
},
"prettier": {
"description": "Opinionated Code Formatter",
"image": "https://prettier.io/icon.png",
Expand Down
1 change: 1 addition & 0 deletions .automation/generated/linter-versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"phpstan": "1.9.4",
"pmd": "6.48.0",
"powershell": "7.3.1",
"powershell_formatter": "5.1.22621",
"prettier": "2.8.1",
"proselint": "0.13.0",
"protolint": "0.42.2",
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Write-Output "hello world!"

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@{
'Hello'='World'
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Write-Output "hello world!"

4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ RUN curl --retry 5 --retry-delay 5 -sLO "${ARM_TTK_URI}" \
# powershell installation
&& pwsh -c 'Install-Module -Name PSScriptAnalyzer -RequiredVersion ${PSSA_VERSION} -Scope AllUsers -Force' \

# powershell_formatter installation
# Next line commented because already managed by another linter
# RUN pwsh -c 'Install-Module -Name PSScriptAnalyzer -RequiredVersion ${PSSA_VERSION} -Scope AllUsers -Force'

# protolint installation
# Managed with COPY --from=protolint /usr/local/bin/protolint /usr/bin/

Expand Down
4 changes: 4 additions & 0 deletions flavors/dotnet/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ RUN curl --retry 5 --retry-delay 5 -sLO "${ARM_TTK_URI}" \
# powershell installation
&& pwsh -c 'Install-Module -Name PSScriptAnalyzer -RequiredVersion ${PSSA_VERSION} -Scope AllUsers -Force' \

# powershell_formatter installation
# Next line commented because already managed by another linter
# RUN pwsh -c 'Install-Module -Name PSScriptAnalyzer -RequiredVersion ${PSSA_VERSION} -Scope AllUsers -Force'

# protolint installation
# Managed with COPY --from=protolint /usr/local/bin/protolint /usr/bin/

Expand Down
1 change: 1 addition & 0 deletions flavors/dotnet/flavor.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"MARKDOWN_MARKDOWN_TABLE_FORMATTER",
"OPENAPI_SPECTRAL",
"POWERSHELL_POWERSHELL",
"POWERSHELL_POWERSHELL_FORMATTER",
"PROTOBUF_PROTOLINT",
"REPOSITORY_CHECKOV",
"REPOSITORY_GIT_DIFF",
Expand Down
1 change: 1 addition & 0 deletions megalinter/descriptors/all_flavors.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@
"MARKDOWN_MARKDOWN_TABLE_FORMATTER",
"OPENAPI_SPECTRAL",
"POWERSHELL_POWERSHELL",
"POWERSHELL_POWERSHELL_FORMATTER",
"PROTOBUF_PROTOLINT",
"REPOSITORY_CHECKOV",
"REPOSITORY_GIT_DIFF",
Expand Down
30 changes: 27 additions & 3 deletions megalinter/descriptors/powershell.megalinter-descriptor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ file_extensions:
- ".pssc"
- ".psrc"
- ".cdxml"
# Reference: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7
# Reference: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux
# Slightly modified to always retrieve latest stable Powershell version
# If changing PWSH_VERSION='latest' to a specific version, use format PWSH_VERSION='tags/v7.0.2'
install:
Expand All @@ -36,8 +36,8 @@ linters:
linter_url: https://github.com/PowerShell/PSScriptAnalyzer
linter_repo: https://github.com/PowerShell/PSScriptAnalyzer
linter_image_url: https://github.com/PowerShell/PSScriptAnalyzer/raw/master/logo.png
linter_rules_configuration_url: https://github.com/PowerShell/PSScriptAnalyzer#explicit
linter_rules_inline_disable_url: https://github.com/PowerShell/PSScriptAnalyzer#suppressing-rules
linter_rules_configuration_url: https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/using-scriptanalyzer?view=ps-modules#explicit
linter_rules_inline_disable_url: https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/using-scriptanalyzer?view=ps-modules#suppressing-rules
config_file_name: .powershell-psscriptanalyzer.psd1
cli_lint_fix_arg_name: "-Fix"
version_extract_regex: "(\\d+) *(\\d+) *(\\d+)"
Expand All @@ -53,3 +53,27 @@ linters:
vscode:
- name: VSCode PowerShell extension
url: https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell
# Internal powershell linter
- class: PowershellLinter
linter_name: powershell_formatter
is_formatter: true
linter_url: https://github.com/PowerShell/PSScriptAnalyzer
linter_repo: https://github.com/PowerShell/PSScriptAnalyzer
linter_image_url: https://github.com/PowerShell/PSScriptAnalyzer/raw/master/logo.png
linter_rules_configuration_url: https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/using-scriptanalyzer?view=ps-modules#explicit
linter_rules_inline_disable_url: https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/using-scriptanalyzer?view=ps-modules#suppressing-rules
config_file_name: .powershell-psscriptanalyzer.psd1
test_folder: powershell_formatter
version_extract_regex: "(\\d+) *(\\d+) *(\\d+)"
examples:
- 'pwsh -NoProfile -NoLogo -Command "Invoke-Formatter -ScriptDefinition ''write-host Hello World''"'
- 'pwsh -NoProfile -NoLogo -Command "Invoke-Formatter -Settings .powershell-psscriptanalyzer.psd1 -ScriptDefinition ''write-host Hello World''"'
# If changing PWSH_VERSION='latest' to a specific version, use format PWSH_VERSION='tags/v7.0.2'
install:
dockerfile:
- ARG PSSA_VERSION='latest'
- RUN pwsh -c 'Install-Module -Name PSScriptAnalyzer -RequiredVersion ${PSSA_VERSION} -Scope AllUsers -Force'
ide:
vscode:
- name: VSCode PowerShell extension
url: https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
"PHP_PSALM",
"PHP_PHPLINT",
"POWERSHELL_POWERSHELL",
"POWERSHELL_POWERSHELL_FORMATTER",
"PROTOBUF_PROTOLINT",
"PUPPET_PUPPET_LINT",
"PYTHON_PYLINT",
Expand Down
17 changes: 13 additions & 4 deletions megalinter/linters/PowershellLinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ def __init__(self, params=None, linter_config=None):

# Build the CLI command to call to lint a file with a powershell script
def build_lint_command(self, file=None):
pwsh_script = ["Invoke-ScriptAnalyzer -EnableExit"]
if self.linter_name == "powershell":
pwsh_script = ["Invoke-ScriptAnalyzer -EnableExit"]
elif self.linter_name == "powershell_formatter":
pwsh_script = ["Invoke-Formatter"]

if self.config_file is not None:
pwsh_script[0] += " -Settings " + self.config_file
pwsh_script[0] += f" -Path '{file}'"
if self.apply_fixes is True and self.cli_lint_fix_arg_name is not None:
pwsh_script[0] += f" {self.cli_lint_fix_arg_name}"

if self.linter_name == "powershell":
pwsh_script[0] += f" -Path '{file}'"
elif self.linter_name == "powershell_formatter":
pwsh_script[0] += f" -ScriptDefinition (Get-Content -Path '{file}' -Raw) > '{file}'"

if self.linter_name == "powershell" and self.apply_fixes is True and self.cli_lint_fix_arg_name is not None:
pwsh_script[0] += f" {self.cli_lint_fix_arg_name}"
cmd = [
self.cli_executable,
"-NoProfile",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# !/usr/bin/env python3
"""
Unit tests for POWERSHELL linter powershell_formatter
This class has been automatically @generated by .automation/build.py, please do not update it manually
"""

from unittest import TestCase

from megalinter.tests.test_megalinter.LinterTestRoot import LinterTestRoot


class powershell_powershell_formatter_test(TestCase, LinterTestRoot):
descriptor_id = "POWERSHELL"
linter_name = "powershell_formatter"

0 comments on commit 2eb9c7d

Please sign in to comment.