├── .gitattributes ├── .github ├── FUNDING.yml ├── main.workflow └── workflows │ └── push.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── README.md ├── action.yml ├── build.ps1 ├── entrypoint.ps1 ├── media └── example.png └── psakeFile.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: devblackops 4 | patreon: devblackops 5 | -------------------------------------------------------------------------------- /.github/main.workflow: -------------------------------------------------------------------------------- 1 | workflow "script-analysis" { 2 | resolves = ["analyze"] 3 | on = "push" 4 | } 5 | 6 | workflow "pr-script-analysis" { 7 | on = "pull_request" 8 | resolves = "analyze-pr" 9 | } 10 | 11 | action "filter-to-pr-open-synced" { 12 | uses = "actions/bin/filter@master" 13 | args = "action 'opened|synchronize'" 14 | } 15 | 16 | action "analyze-pr" { 17 | uses = "devblackops/github-action-psscriptanalyzer@master" 18 | needs = "filter-to-pr-open-synced" 19 | secrets = ["GITHUB_TOKEN"] 20 | } 21 | 22 | action "analyze" { 23 | uses = "devblackops/github-action-psscriptanalyzer@master" 24 | secrets = ["GITHUB_TOKEN"] 25 | } -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | name: Run PSSA 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - name: lint 10 | uses: devblackops/github-action-psscriptanalyzer@master 11 | with: 12 | sendComment: true 13 | failOnErrors: true 14 | failOnWarnings: true 15 | failOnInfos: false 16 | repoToken: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## [2.4.0] - 2021-10-22 9 | 10 | ### Changed 11 | 12 | - [**#PR18**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/18) - Updated pwsh, Ubuntu, and PSSA versions (via [@alagoutte](https://github.com/alagoutte)) 13 | - pwsh `7.0.3` -> `7.1.5` 14 | - Ubuntu `18.04` -> `20.04` 15 | - PSSA `1.19.1` -> `1.20.0` 16 | 17 | ## [2.3.1] - 2021-02-27 18 | 19 | ### Fixed 20 | 21 | - [**#PR15**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/15) - Typo in code comment (via [@revolter](https://github.com/revolter)) 22 | 23 | ## [2.3.0] - 2020-08-31 24 | 25 | ### Fixed 26 | 27 | - [**#PR13**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/13) - Remove `outputs` section from `action.yml` to resolve error when `outputs` is empty (via [@SleepySysadmin](https://github.com/SleepySysadmin)) 28 | 29 | ### Changed 30 | 31 | - Updated docker image to `powershell:7.0.3-ubuntu-18.04`. 32 | 33 | - Updated `PSScriptAnalyzer` to `1.19.1`. 34 | 35 | ## [2.2.0] - 2020-06-30 36 | 37 | ### Fixed 38 | 39 | - [**#PR8**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/8) - Fix SendComment (Only if RepoToken is available) (via [@alagoutte](https://github.com/alagoutte)) 40 | 41 | ### Changed 42 | 43 | - [**#PR10**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/10) - Update checkout action to v2 (`actions/checkout@v2`) (via [@alagoutte](https://github.com/alagoutte)) 44 | 45 | - [**#PR7**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/7) - Updated PSScriptAnalyzer to `1.19.0` (via [@alagoutte](https://github.com/alagoutte)) 46 | 47 | - [**#PR6**](https://github.com/devblackops/github-action-psscriptanalyzer/pull/6) - Updated PowerShell Docker iamge to `7.0.1` (via [@alagoutte](https://github.com/alagoutte)) 48 | 49 | ## [2.1.1] - 2020-05-15 50 | 51 | ### Fixed 52 | 53 | - Fixed reference to warning environment variable (`INPUT_FAILONWARNINGS`) (via [@CrazyCodeUK](https://github.com/CrazyCodeUK)) 54 | 55 | ## [2.1.0] - 2020-05-15 56 | 57 | ### Changed 58 | 59 | - Bumped PSScriptAnalyzer to `1.18.3` (via [@alagoutte](https://github.com/alagoutte)) 60 | 61 | ## [2.0.0] - 2019-08-28 62 | 63 | ### Changed 64 | 65 | - Refactored to new GitHub Action syntax 66 | - Renamed options to: 67 | - rootPath 68 | - settingsPath 69 | - repoToken 70 | - sendComment 71 | - failOnErrors 72 | - failOnWarnings 73 | - failOnInfos 74 | - Allow failing the GitHub Action on PSSA error, warning, or informational issues 75 | 76 | ## [1.2.1] - 2019-01-15 77 | 78 | ### Fixed 79 | 80 | - Action will now only attempt to post a PR comment if a valid comments URL is found in the action payload 81 | 82 | ## [1.2.0] - 2019-01-14 83 | 84 | ### Changed 85 | 86 | - Reorganize project so it is compatible with GitHub Marketplace 87 | 88 | ## [1.1.0] - 2018-01-06 89 | 90 | ### Changed 91 | 92 | - Call PowerShell entrypoint script directly instead of calling bash first. 93 | - Allow disabling sending PSScriptAnalyzer results back to PR by setting the environment variable `PSSCRIPTANALYZER_SEND_COMMENT` to `false` or `0`. 94 | 95 | ## [1.0.1] - 2018-12-28 96 | 97 | ### Fixed 98 | 99 | - Fix logic and only post a GitHub comment to the PR if issues were found. 100 | 101 | ## [1.0.0] - 2018-12-28 102 | 103 | ### Added 104 | 105 | - Initial release using PSScriptAnalyzer version `1.17.1` 106 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/powershell:7.1.5-ubuntu-20.04 as base 2 | SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] 3 | RUN Set-PSRepository -Name PSGallery -InstallationPolicy Trusted; \ 4 | Install-Module PSScriptAnalyzer -RequiredVersion 1.20.0 -Scope AllUsers -Repository PSGallery 5 | 6 | FROM base as analyzer 7 | LABEL "com.github.actions.name" = "PSScriptAnalyzer" 8 | LABEL "com.github.actions.description" = "Run PSScriptAnalyzer tests" 9 | LABEL "com.github.actions.icon"="check-square" 10 | LABEL "com.github.actions.color"="green" 11 | 12 | LABEL "name" = "github-action-psscriptanalyzer" 13 | LABEL "version" = "2.4.0" 14 | LABEL "repository" = "https://github.com/devblackops/github-action-psscriptanalyzer" 15 | LABEL "homepage" = "https://github.com/PowerShell/PSScriptAnalyzer" 16 | LABEL "maintainer" = "Brandon Olin " 17 | 18 | ADD entrypoint.ps1 /entrypoint.ps1 19 | 20 | COPY LICENSE README.md / 21 | 22 | RUN chmod +x /entrypoint.ps1 23 | 24 | ENTRYPOINT ["pwsh", "/entrypoint.ps1"] 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Brandon Olin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github-action-psscriptanalyzer 2 | 3 | [![GitHub Actions Status][github-actions-badge]][github-actions-build] 4 | 5 | [GitHub Action](https://github.com/features/actions) to run [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) static code analysis checks on PowerShell for [Pull Requests](https://help.github.com/articles/about-pull-requests/). 6 | 7 | ## Success Criteria 8 | 9 | By default, this action will succeed if **zero** PSScriptAnalyzer **errors** and **warnings** are found. 10 | Failing on errors, warnings, or informational issues can be configured. See [Usage](#Usage) below. 11 | The sending of comments back to the PR if the action fails can be disabled if desired. 12 | 13 | ## Usage 14 | 15 | ### Basic 16 | 17 | Basic configuration that will run PSSA and fail on errors or warnings, and send a comment back to the PR with a summary. 18 | Note, that `repoToken` is required for sending comments back. 19 | 20 | ```yaml 21 | name: CI 22 | on: [pull_request] 23 | jobs: 24 | lint: 25 | name: Run PSSA 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v2 29 | - name: lint 30 | uses: devblackops/github-action-psscriptanalyzer@master 31 | with: 32 | repoToken: ${{ secrets.GITHUB_TOKEN }} 33 | ``` 34 | 35 | ### Advanced 36 | 37 | Advanced configuration that will run PSSA only in the `MyModule` directory, with custom PSSA settings, and fail on errors, warnings, or informational issues. 38 | A comment back to the PR with the PSSA summary will also be sent if any issues were detected. 39 | 40 | ```yaml 41 | name: CI 42 | on: [pull_request] 43 | jobs: 44 | lint: 45 | name: Run PSSA 46 | runs-on: ubuntu-latest 47 | steps: 48 | - uses: actions/checkout@v2 49 | - name: lint 50 | uses: devblackops/github-action-psscriptanalyzer@master 51 | with: 52 | rootPath: MyModule 53 | settingsPath: pssa_settings.psd1 54 | sendComment: true 55 | repoToken: ${{ secrets.GITHUB_TOKEN }} 56 | failOnErrors: true 57 | failOnWarnings: true 58 | failOnInfos: true 59 | ``` 60 | 61 | ### Docker 62 | 63 | Use the Docker Hub version of the Action instead of building the container during the check. 64 | 65 | ```yaml 66 | name: CI 67 | on: [pull_request] 68 | jobs: 69 | lint: 70 | name: Run PSSA 71 | runs-on: ubuntu-latest 72 | steps: 73 | - uses: actions/checkout@v2 74 | - name: lint 75 | uses: docker://devblackops/github-action-psscriptanalyzer:2.3.0 76 | with: 77 | repoToken: ${{ secrets.GITHUB_TOKEN }} 78 | ``` 79 | 80 | ## Inputs 81 | 82 | | Name | Default | Description | 83 | |------|---------|-------------| 84 | | rootPath | \ | The root directory to run PSScriptAnalyzer on. By default, this is the root of the repository. 85 | | settingsPath | \ | The path to a PSScriptAnalyser settings file to control rules to execute. 86 | | sendComment | true | Enable/disable sending comments with PSScriptAnalyzer results back to PR. 87 | | repoToken | \ | GitHub token the action will use to send comments back to PR with. Use `${{ secrets.GITHUB_TOKEN }}`. 88 | | failOnErrors | true | Enable/disable failing the action on PSScriptAnalyzer error items. 89 | | failOnWarnings | true | Enable/disable failing the action on PSScriptAnalyzer warning items. 90 | | failOnInfos | false | Enable/disable failing the action on PSScriptAnalyzer informational items. 91 | 92 | ## Example 93 | 94 | ![](media/example.png) 95 | 96 | [github-actions-badge]: https://github.com/devblackops/github-action-psscriptanalyzer/workflows/CI/badge.svg 97 | [github-actions-build]: https://github.com/devblackops/github-action-psscriptanalyzer/actions 98 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: PSScriptAnalyzer checks 2 | author: Brandon Olin 3 | description: GitHub Action to run PSScriptAnalyzer static code analysis checks on Pull Requests 4 | inputs: 5 | rootPath: 6 | description: The root directory to run PSScriptAnalyzer on. By default, this is the root of the repository. 7 | required: false 8 | settingsPath: 9 | description: The path to a PSScriptAnalyser settings file to control rules to execute. 10 | required: false 11 | repoToken: 12 | description: GitHub token the action will use to send comments back to PR with. 13 | required: false 14 | sendComment: 15 | description: Send comment back to PR with PSScriptAnalyzer summary if any issues where found. 16 | required: false 17 | default: true 18 | failOnErrors: 19 | description: Enable/disable failing the action on PSScriptAnalyzer error items. 20 | required: false 21 | default: true 22 | failOnWarnings: 23 | description: Enable/disable failing the action on PSScriptAnalyzer warning items. 24 | required: false 25 | default: true 26 | failOnInfos: 27 | description: Enable/disable failing the action on PSScriptAnalyzer informational items. 28 | required: false 29 | default: false 30 | runs: 31 | using: docker 32 | image: Dockerfile 33 | branding: 34 | icon: check-square 35 | color: green 36 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | [cmdletbinding(DefaultParameterSetName = 'task')] 2 | param( 3 | [parameter(ParameterSetName = 'task', Position = 0)] 4 | [string[]]$Task = 'default', 5 | 6 | [parameter(ParameterSetName = 'help')] 7 | [switch]$Help, 8 | 9 | [switch]$Bootstrap 10 | ) 11 | 12 | $ErrorActionPreference = 'Stop' 13 | 14 | # Bootstrap dependencies 15 | if ($Bootstrap.IsPresent) { 16 | Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null 17 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 18 | if (-not (Get-Module -Name PSDepend -ListAvailable)) { 19 | Install-Module -Name PSDepend -Repository PSGallery -Scope CurrentUser 20 | } 21 | Import-Module -Name PSDepend -Verbose:$false 22 | Invoke-PSDepend -Path './requirements.psd1' -Install -Import -Force -WarningAction SilentlyContinue 23 | } 24 | 25 | # Execute psake task(s) 26 | $psakeFile = './psakeFile.ps1' 27 | Set-BuildEnvironment -Force -WarningAction SilentlyContinue 28 | if ($Help.IsPresent) { 29 | Get-PSakeScriptTasks -buildFile $psakeFile | 30 | Format-Table -Property Name, Description, Alias, DependsOn 31 | } else { 32 | Invoke-psake -buildFile $psakeFile -taskList $Task -nologo -Verbose:($VerbosePreference -eq 'Continue') 33 | exit ([int](-not $psake.build_success)) 34 | } 35 | -------------------------------------------------------------------------------- /entrypoint.ps1: -------------------------------------------------------------------------------- 1 | [cmdletbinding()] 2 | param() 3 | 4 | $ErrorActionPreference = 'Stop' 5 | 6 | $nl = [Environment]::NewLine 7 | 8 | $analyzeParams = @{ 9 | Recurse = $true 10 | } 11 | 12 | # By default, run PSScriptAnalyzer on the whole repository 13 | # but allow overriding this with INPUT_ROOTPATH environment variable 14 | if ($env:INPUT_ROOTPATH) { 15 | $analyzeParams.Path = Join-Path '/github/workspace' $env:INPUT_ROOTPATH 16 | } else { 17 | $analyzeParams.Path = $env:GITHUB_WORKSPACE 18 | } 19 | 20 | # Path to custom script analyzer settings 21 | if ($env:INPUT_SETTINGSPATH) { 22 | $analyzeParams.Settings = Join-Path '/github/workspace' $env:INPUT_SETTINGSPATH 23 | } 24 | 25 | # Run PSScriptAnalyzer 26 | $issues = Invoke-ScriptAnalyzer @analyzeParams 27 | $errors = $issues.Where({$_.Severity -eq 'Error'}) 28 | $warnings = $issues.Where({$_.Severity -eq 'Warning'}) 29 | $infos = $issues.Where({$_.Severity -eq 'Information'}) 30 | 31 | # Create comment string 32 | $comment = '**PSScriptAnalyzer results:**' 33 | $comment += '{0}
Errors: [{1}], Warnings: [{2}], Information: [{3}]

{4}{5}```' -f $nl, $errors.Count, $warnings.Count, $infos.Count, $nl, $nl 34 | if ($errors.Count -gt 0) { 35 | $comment += $nl + ($errors | Format-List -Property RuleName, Severity, ScriptName, Line, Message | Out-String -Width 80).Trim() 36 | } 37 | if ($warnings.Count -gt 0) { 38 | $comment += $nl+ $nl + ($warnings | Format-List -Property RuleName, Severity, ScriptName, Line, Message | Out-String -Width 80).Trim() 39 | } 40 | if ($infos.Count -gt 0) { 41 | $comment += $nl + $nl + ($infos | Format-List -Property RuleName, Severity, ScriptName, Line, Message | Out-String -Width 80).Trim() 42 | } 43 | $comment += '{0}{1}```{2}

' -f $nl, $nl, $nl 44 | Write-Output $comment 45 | 46 | # Get comment URL 47 | $ghEvent = Get-Content -Path $env:GITHUB_EVENT_PATH | ConvertFrom-Json -Depth 30 48 | $commentsUrl = $ghEvent.pull_request.comments_url 49 | 50 | # Send comment back to PR if any issues were found 51 | if ($commentsUrl -and ($env:INPUT_SENDCOMMENT -eq "$true" -or $env:INPUT_SENDCOMMENT -eq 1) -and $env:INPUT_REPOTOKEN -and ($errors.Count -gt 0 -or $warnings.Count -gt 0 -or $infos.Count -gt 0)) { 52 | $params = @{ 53 | Uri = $commentsUrl 54 | Method = 'Post' 55 | Headers = @{ 56 | Authorization = "token $env:INPUT_REPOTOKEN" 57 | } 58 | ContentType = 'application/json' 59 | Body = @{body = $comment} | ConvertTo-Json 60 | } 61 | Invoke-RestMethod @params > $null 62 | } 63 | 64 | $exitCode = 0 65 | if ($env:INPUT_FAILONERRORS -eq 'true' -or $env:INPUT_FAILONERRORS -eq 1) { $exitCode += $errors.Count} 66 | if ($env:INPUT_FAILONWARNINGS -eq 'true' -or $env:INPUT_FAILONWARNINGS -eq 1) { $exitCode += $warnings.Count} 67 | if ($env:INPUT_FAILONINFOS -eq 'true' -or $env:INPUT_FAILONINFOS -eq 1) { $exitCode += $infos.Count} 68 | exit $exitCode 69 | -------------------------------------------------------------------------------- /media/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devblackops/github-action-psscriptanalyzer/854038567344559afaaa8ccb7a014452b99d86ee/media/example.png -------------------------------------------------------------------------------- /psakeFile.ps1: -------------------------------------------------------------------------------- 1 | [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '')] 2 | param() 3 | 4 | task default -depends Build 5 | 6 | task Init { 7 | $script:dockerAcct = 'devblackops' 8 | $script:imageName = $env:BHProjectName 9 | $script:dockerRepo = "$dockerAcct/$imageName" 10 | $script:version = '2.4.0' 11 | } 12 | 13 | task Build -depends Init { 14 | "Building [$script:version]" 15 | exec { 16 | docker build -t "$dockerRepo`:$version" . 17 | } 18 | } 19 | 20 | task Login { 21 | exec { 22 | docker login 23 | } 24 | } 25 | 26 | task Push -depends Build, Login { 27 | exec { 28 | docker push "$dockerRepo`:$version" 29 | } 30 | } 31 | 32 | task ? { 33 | 'Available tasks:' 34 | $psake.context.Peek().Tasks.Keys | Sort-Object 35 | } 36 | --------------------------------------------------------------------------------