diff --git a/.github/linters/.jscpd.json b/.github/linters/.jscpd.json new file mode 100644 index 0000000..23970e8 --- /dev/null +++ b/.github/linters/.jscpd.json @@ -0,0 +1,10 @@ +{ + "threshold": 0, + "reporters": [ + "consoleFull" + ], + "ignore": [ + "**/tests/**" + ], + "absolute": true +} diff --git a/.github/linters/.powershell-psscriptanalyzer.psd1 b/.github/linters/.powershell-psscriptanalyzer.psd1 index 6779d06..09cc3d0 100644 --- a/.github/linters/.powershell-psscriptanalyzer.psd1 +++ b/.github/linters/.powershell-psscriptanalyzer.psd1 @@ -1,17 +1,56 @@ -#Documentation: https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-settings -@{ - #CustomRulePath='path\to\CustomRuleModule.psm1' - #RecurseCustomRulePath='path\of\customrules' - #Severity = @( - # 'Error' - # 'Warning' - #) - #IncludeDefaultRules=${true} +@{ + Rules = @{ + PSAlignAssignmentStatement = @{ + Enable = $true + CheckHashtable = $true + } + PSAvoidLongLines = @{ + Enable = $true + MaximumLineLength = 150 + } + PSAvoidSemicolonsAsLineTerminators = @{ + Enable = $true + } + PSPlaceCloseBrace = @{ + Enable = $true + NewLineAfter = $false + IgnoreOneLineBlock = $true + NoEmptyLineBefore = $false + } + PSPlaceOpenBrace = @{ + Enable = $true + OnSameLine = $true + NewLineAfter = $true + IgnoreOneLineBlock = $true + } + PSProvideCommentHelp = @{ + Enable = $true + ExportedOnly = $false + BlockComment = $true + VSCodeSnippetCorrection = $false + Placement = 'begin' + } + PSUseConsistentIndentation = @{ + Enable = $true + IndentationSize = 4 + PipelineIndentation = 'IncreaseIndentationForFirstPipeline' + Kind = 'space' + } + PSUseConsistentWhitespace = @{ + Enable = $true + CheckInnerBrace = $true + CheckOpenBrace = $true + CheckOpenParen = $true + CheckOperator = $true + CheckPipe = $true + CheckPipeForRedundantWhitespace = $true + CheckSeparator = $true + CheckParameter = $true + IgnoreAssignmentOperatorInsideHashTable = $true + } + } ExcludeRules = @( - 'PSAvoidUsingWriteHost' + 'PSMissingModuleManifestField', # This rule is not applicable until the module is built. + 'PSUseToExportFieldsInManifest' ) - #IncludeRules = @( - # 'PSAvoidUsingWriteHost', - # 'MyCustomRuleName' - #) } diff --git a/.github/linters/.textlintrc b/.github/linters/.textlintrc new file mode 100644 index 0000000..db48de8 --- /dev/null +++ b/.github/linters/.textlintrc @@ -0,0 +1,513 @@ +{ + "filters": { + "comments": true + }, + "rules": { + "terminology": { + "defaultTerms": false, + "terms": [ + "Airbnb", + "Android", + "AppleScript", + "AppVeyor", + "AVA", + "BrowserStack", + "Browsersync", + "Codecov", + "CodePen", + "CodeSandbox", + "DefinitelyTyped", + "EditorConfig", + "ESLint", + "GitHub", + "GraphQL", + "GraphiQL", + "iOS", + "JavaScript", + "JetBrains", + "jQuery", + "LinkedIn", + "Lodash", + "MacBook", + "Markdown", + "OpenType", + "PayPal", + "PhpStorm", + "PowerShell", + "PlayStation", + "RubyMine", + "Sass", + "SemVer", + "TypeScript", + "UglifyJS", + "Wasm", + "WebAssembly", + "WebStorm", + "WordPress", + "YouTube", + [ + "Common[ .]js", + "CommonJS" + ], + [ + "JSDocs?", + "JSDoc" + ], + [ + "Node[ .]js", + "Node.js" + ], + [ + "React[ .]js", + "React" + ], + [ + "SauceLabs", + "Sauce Labs" + ], + [ + "StackOverflow", + "Stack Overflow" + ], + [ + "styled ?components", + "styled-components" + ], + [ + "HTTP[ /]2(?:\\.0)?", + "HTTP/2" + ], + [ + "OS X", + "macOS" + ], + [ + "Mac ?OS", + "macOS" + ], + [ + "a npm", + "an npm" + ], + "ECMAScript", + [ + "ES2015", + "ES6" + ], + [ + "ES7", + "ES2016" + ], + "3D", + [ + "3-D", + "3D" + ], + "Ajax", + "API", + "APIs", + "API's", + [ + "(? + [OutputType([void])] [CmdletBinding()] + #Requires -Modules Utilities, PowerShellGet, Microsoft.PowerShell.PSResourceGet, Retry, GitHub, PSSemVer [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSReviewUnusedParameter', '', Scope = 'Function', Justification = 'LogGroup - Scoping affects the variables line of sight.' @@ -42,17 +42,37 @@ function Publish-PSModule { $configuration = ConvertFrom-Yaml -Yaml (Get-Content $env:GITHUB_ACTION_INPUT_ConfigurationFile -Raw) } - $autoCleanup = ($configuration.AutoCleanup | IsNotNullOrEmpty) ? $configuration.AutoCleanup -eq 'true' : $env:GITHUB_ACTION_INPUT_AutoCleanup -eq 'true' - $autoPatching = ($configuration.AutoPatching | IsNotNullOrEmpty) ? $configuration.AutoPatching -eq 'true' : $env:GITHUB_ACTION_INPUT_AutoPatching -eq 'true' - $datePrereleaseFormat = ($configuration.DatePrereleaseFormat | IsNotNullOrEmpty) ? $configuration.DatePrereleaseFormat : $env:GITHUB_ACTION_INPUT_DatePrereleaseFormat - $incrementalPrerelease = ($configuration.IncrementalPrerelease | IsNotNullOrEmpty) ? $configuration.IncrementalPrerelease -eq 'true' : $env:GITHUB_ACTION_INPUT_IncrementalPrerelease -eq 'true' - $versionPrefix = ($configuration.VersionPrefix | IsNotNullOrEmpty) ? $configuration.VersionPrefix : $env:GITHUB_ACTION_INPUT_VersionPrefix - $whatIf = ($configuration.WhatIf | IsNotNullOrEmpty) ? $configuration.WhatIf -eq 'true' : $env:GITHUB_ACTION_INPUT_WhatIf -eq 'true' - - $ignoreLabels = (($configuration.IgnoreLabels | IsNotNullOrEmpty) ? $configuration.IgnoreLabels : $env:GITHUB_ACTION_INPUT_IgnoreLabels) -split ',' | ForEach-Object { $_.Trim() } - $majorLabels = (($configuration.MajorLabels | IsNotNullOrEmpty) ? $configuration.MajorLabels : $env:GITHUB_ACTION_INPUT_MajorLabels) -split ',' | ForEach-Object { $_.Trim() } - $minorLabels = (($configuration.MinorLabels | IsNotNullOrEmpty) ? $configuration.MinorLabels : $env:GITHUB_ACTION_INPUT_MinorLabels) -split ',' | ForEach-Object { $_.Trim() } - $patchLabels = (($configuration.PatchLabels | IsNotNullOrEmpty) ? $configuration.PatchLabels : $env:GITHUB_ACTION_INPUT_PatchLabels) -split ',' | ForEach-Object { $_.Trim() } + $autoCleanup = ($configuration.AutoCleanup | IsNotNullOrEmpty) ? + $configuration.AutoCleanup -eq 'true' : + $env:GITHUB_ACTION_INPUT_AutoCleanup -eq 'true' + $autoPatching = ($configuration.AutoPatching | IsNotNullOrEmpty) ? + $configuration.AutoPatching -eq 'true' : + $env:GITHUB_ACTION_INPUT_AutoPatching -eq 'true' + $datePrereleaseFormat = ($configuration.DatePrereleaseFormat | IsNotNullOrEmpty) ? + $configuration.DatePrereleaseFormat : + $env:GITHUB_ACTION_INPUT_DatePrereleaseFormat + $incrementalPrerelease = ($configuration.IncrementalPrerelease | IsNotNullOrEmpty) ? + $configuration.IncrementalPrerelease -eq 'true' : + $env:GITHUB_ACTION_INPUT_IncrementalPrerelease -eq 'true' + $versionPrefix = ($configuration.VersionPrefix | IsNotNullOrEmpty) ? + $configuration.VersionPrefix : + $env:GITHUB_ACTION_INPUT_VersionPrefix + $whatIf = ($configuration.WhatIf | IsNotNullOrEmpty) ? + $configuration.WhatIf -eq 'true' : + $env:GITHUB_ACTION_INPUT_WhatIf -eq 'true' + + $ignoreLabels = (($configuration.IgnoreLabels | IsNotNullOrEmpty) ? + $configuration.IgnoreLabels : + $env:GITHUB_ACTION_INPUT_IgnoreLabels) -split ',' | ForEach-Object { $_.Trim() } + $majorLabels = (($configuration.MajorLabels | IsNotNullOrEmpty) ? + $configuration.MajorLabels : + $env:GITHUB_ACTION_INPUT_MajorLabels) -split ',' | ForEach-Object { $_.Trim() } + $minorLabels = (($configuration.MinorLabels | IsNotNullOrEmpty) ? + $configuration.MinorLabels : + $env:GITHUB_ACTION_INPUT_MinorLabels) -split ',' | ForEach-Object { $_.Trim() } + $patchLabels = (($configuration.PatchLabels | IsNotNullOrEmpty) ? + $configuration.PatchLabels : + $env:GITHUB_ACTION_INPUT_PatchLabels) -split ',' | ForEach-Object { $_.Trim() } Write-Output '-------------------------------------------------' Write-Output "Auto cleanup enabled: [$autoCleanup]" @@ -130,7 +150,9 @@ function Publish-PSModule { $majorRelease = ($labels | Where-Object { $majorLabels -contains $_ }).Count -gt 0 $minorRelease = ($labels | Where-Object { $minorLabels -contains $_ }).Count -gt 0 -and -not $majorRelease - $patchRelease = (($labels | Where-Object { $patchLabels -contains $_ }).Count -gt 0 -or $autoPatching) -and -not $majorRelease -and -not $minorRelease + $patchRelease = ( + ($labels | Where-Object { $patchLabels -contains $_ } + ).Count -gt 0 -or $autoPatching) -and -not $majorRelease -and -not $minorRelease Write-Output '-------------------------------------------------' Write-Output "Create a release: [$createRelease]" @@ -159,31 +181,38 @@ function Publish-PSModule { Write-Warning 'Could not find the latest release version. Using ''0.0.0'' as the version.' $ghReleaseVersion = New-PSSemVer -Version '0.0.0' } - Write-Verbose '-------------------------------------------------' - Write-Verbose 'GitHub version:' - Write-Verbose ($ghReleaseVersion | Format-Table | Out-String) - Write-Verbose $ghReleaseVersion.ToString() - Write-Verbose '-------------------------------------------------' + Write-Output '-------------------------------------------------' + Write-Output 'GitHub version:' + Write-Output ($ghReleaseVersion | Format-Table | Out-String) + Write-Output $ghReleaseVersion.ToString() + Write-Output '-------------------------------------------------' } LogGroup 'Get latest version - PSGallery' { try { - $psGalleryVersion = New-PSSemVer -Version (Find-PSResource -Name $Name -Repository PSGallery -Verbose:$false).Version + Retry -Count 5 -Delay 10 { + Write-Output "Finding module [$Name] in the PowerShell Gallery." + $latest = Find-PSResource -Name $Name -Repository PSGallery -Verbose:$false + Write-Output ($latest | Format-Table | Out-String) + } -Catch { + throw $_ + } + $psGalleryVersion = New-PSSemVer -Version $latest.Version } catch { Write-Warning 'Could not find module online. Using ''0.0.0'' as the version.' $psGalleryVersion = New-PSSemVer -Version '0.0.0' } - Write-Verbose '-------------------------------------------------' - Write-Verbose 'PSGallery version:' - Write-Verbose ($psGalleryVersion | Format-Table | Out-String) - Write-Verbose $psGalleryVersion.ToString() - Write-Verbose '-------------------------------------------------' + Write-Output '-------------------------------------------------' + Write-Output 'PSGallery version:' + Write-Output ($psGalleryVersion | Format-Table | Out-String) + Write-Output $psGalleryVersion.ToString() + Write-Output '-------------------------------------------------' } LogGroup 'Get latest version - Manifest' { Add-PSModulePath -Path (Split-Path -Path $ModulePath -Parent) $manifestFilePath = Join-Path $ModulePath "$Name.psd1" - Write-Verbose "Module manifest file path: [$manifestFilePath]" + Write-Output "Module manifest file path: [$manifestFilePath]" if (-not (Test-Path -Path $manifestFilePath)) { Write-Error "Module manifest file not found at [$manifestFilePath]" return @@ -196,23 +225,23 @@ function Publish-PSModule { $manifestVersion = New-PSSemVer -Version '0.0.0' } } - Write-Verbose '-------------------------------------------------' - Write-Verbose 'Manifest version:' - Write-Verbose ($manifestVersion | Format-Table | Out-String) - Write-Verbose $manifestVersion.ToString() - Write-Verbose '-------------------------------------------------' + Write-Output '-------------------------------------------------' + Write-Output 'Manifest version:' + Write-Output ($manifestVersion | Format-Table | Out-String) + Write-Output $manifestVersion.ToString() + Write-Output '-------------------------------------------------' } LogGroup 'Get latest version' { - Write-Verbose "GitHub: [$($ghReleaseVersion.ToString())]" - Write-Verbose "PSGallery: [$($psGalleryVersion.ToString())]" - Write-Verbose "Manifest: [$($manifestVersion.ToString())] (ignored)" + Write-Output "GitHub: [$($ghReleaseVersion.ToString())]" + Write-Output "PSGallery: [$($psGalleryVersion.ToString())]" + Write-Output "Manifest: [$($manifestVersion.ToString())] (ignored)" $latestVersion = New-PSSemVer -Version ($psGalleryVersion, $ghReleaseVersion | Sort-Object -Descending | Select-Object -First 1) - Write-Verbose '-------------------------------------------------' - Write-Verbose 'Latest version:' - Write-Verbose ($latestVersion | Format-Table | Out-String) - Write-Verbose $latestVersion.ToString() - Write-Verbose '-------------------------------------------------' + Write-Output '-------------------------------------------------' + Write-Output 'Latest version:' + Write-Output ($latestVersion | Format-Table | Out-String) + Write-Output $latestVersion.ToString() + Write-Output '-------------------------------------------------' } LogGroup 'Calculate new version' { @@ -237,7 +266,7 @@ function Publish-PSModule { if ($createPrerelease) { Write-Output "Adding a prerelease tag to the version using the branch name [$prereleaseName]." - Write-Verbose ($releases | Where-Object { $_.tagName -like "*$prereleaseName*" } | + Write-Output ($releases | Where-Object { $_.tagName -like "*$prereleaseName*" } | Select-Object -Property name, isPrerelease, isLatest, publishedAt | Format-Table -AutoSize | Out-String) $newVersion.Prerelease = $prereleaseName @@ -254,7 +283,17 @@ function Publish-PSModule { $newVersionString = "$($newVersion.Major).$($newVersion.Minor).$($newVersion.Patch)" # PowerShell Gallery - $psGalleryPrereleases = Find-PSResource -Name $Name -Repository PSGallery -Verbose:$false -Version * -Prerelease + $params = @{ + Name = $Name + Version = '*' + Prerelease = $true + Repository = 'PSGallery' + Verbose = $false + ErrorAction = 'SilentlyContinue' + } + Write-Output 'Finding the latest prerelease version in the PowerShell Gallery.' + Write-Output ($params | Format-Table | Out-String) + $psGalleryPrereleases = Find-PSResource @params $psGalleryPrereleases = $psGalleryPrereleases | Where-Object { $_.Version -like "$newVersionString" } $psGalleryPrereleases = $psGalleryPrereleases | Where-Object { $_.Prerelease -like "$prereleaseName*" } $latestPSGalleryPrerelease = $psGalleryPrereleases.Prerelease | ForEach-Object { @@ -275,24 +314,24 @@ function Publish-PSModule { $latestPrereleaseNumber = [Math]::Max($latestPSGalleryPrerelease, $latestGHPrereleases) $latestPrereleaseNumber++ - $latestPrereleaseNumber = $latestPrereleaseNumber.PadLeft(3,'0') + $latestPrereleaseNumber = ([string]$latestPrereleaseNumber).PadLeft(3, '0') $newVersion.Prerelease += $latestPrereleaseNumber } } - Write-Verbose '-------------------------------------------------' - Write-Verbose 'New version:' - Write-Verbose ($newVersion | Format-Table | Out-String) - Write-Verbose $newVersion.ToString() - Write-Verbose '-------------------------------------------------' + Write-Output '-------------------------------------------------' + Write-Output 'New version:' + Write-Output ($newVersion | Format-Table | Out-String) + Write-Output $newVersion.ToString() + Write-Output '-------------------------------------------------' } - Write-Verbose "New version is [$($newVersion.ToString())]" + Write-Output "New version is [$($newVersion.ToString())]" LogGroup 'Update module manifest' { - Write-Verbose 'Bump module version -> module metadata: Update-ModuleMetadata' + Write-Output 'Bump module version -> module metadata: Update-ModuleMetadata' $manifestNewVersion = "$($newVersion.Major).$($newVersion.Minor).$($newVersion.Patch)" Set-ModuleManifest -Path $manifestFilePath -ModuleVersion $manifestNewVersion -Verbose:$false if ($createPrerelease) { - Write-Verbose "Prerelease is: [$($newVersion.Prerelease)]" + Write-Output "Prerelease is: [$($newVersion.Prerelease)]" Set-ModuleManifest -Path $manifestFilePath -Prerelease $($newVersion.Prerelease) -Verbose:$false } @@ -305,9 +344,16 @@ function Publish-PSModule { if ($createPrerelease -or $createRelease -or $whatIf) { LogGroup 'Publish-ToPSGallery' { - Write-Verbose "Publish module to PowerShell Gallery using [$APIKey]" + if ($createPrerelease) { + $publishPSVersion = "$($newVersion.Major).$($newVersion.Minor).$($newVersion.Patch)-$($newVersion.Prerelease)" + $psGalleryReleaseLink = "https://www.powershellgallery.com/packages/$Name/$publishPSVersion" + } else { + $publishPSVersion = $newVersion.ToString() + $psGalleryReleaseLink = "https://www.powershellgallery.com/packages/$Name/$($newVersion.ToString())" + } + Write-Output "Publish module to PowerShell Gallery using [$APIKey]" if ($whatIf) { - Write-Verbose "Publish-PSResource -Path $ModulePath -Repository PSGallery -ApiKey $APIKey -Verbose" + Write-Output "Publish-PSResource -Path $ModulePath -Repository PSGallery -ApiKey $APIKey" } else { try { Publish-PSResource -Path $ModulePath -Repository PSGallery -ApiKey $APIKey @@ -317,10 +363,13 @@ function Publish-PSModule { } } if ($whatIf) { - Write-Output "gh pr comment $($pull_request.number) -b 'Published to the PowerShell Gallery [$newVersion]($releaseURL) has been created.'" + Write-Output ( + "gh pr comment $($pull_request.number) -b 'Published to the" + + " PowerShell Gallery [$publishPSVersion]($psGalleryReleaseLink) has been created.'" + ) } else { - Write-Output "::notice::Module [$Name - $newVersion] published to the PowerShell Gallery." - gh pr comment $pull_request.number -b "Module [$Name - $newVersion] published to the PowerShell Gallery." + Write-GitHubNotice "Module [$Name - $publishPSVersion] published to the PowerShell Gallery." + gh pr comment $pull_request.number -b "Module [$Name - $publishPSVersion]($psGalleryReleaseLink) published to the PowerShell Gallery." if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to comment on the pull request.' exit $LASTEXITCODE @@ -329,7 +378,7 @@ function Publish-PSModule { } LogGroup 'New-GitHubRelease' { - Write-Verbose 'Create new GitHub release' + Write-Output 'Create new GitHub release' if ($createPrerelease) { if ($whatIf) { Write-Output "WhatIf: gh release create $newVersion --title $newVersion --target $prHeadRef --generate-notes --prerelease" @@ -360,7 +409,7 @@ function Publish-PSModule { exit $LASTEXITCODE } } - Write-Output "::notice::Release created: [$newVersion]" + Write-GitHubNotice "Release created: [$newVersion]" } }