forked from StartAutomating/PSDevOps
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request StartAutomating#76 from StartAutomating/PSDevOpsAn…
…dDocumentation Adding Get-PSDevOps and Documentation
- Loading branch information
Showing
4 changed files
with
368 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
Write-FormatView -TypeName PSDevOps -Property Name, ScriptType, Synopsis, Parameters -VirtualProperty @{ | ||
Parameters = { | ||
@(foreach ($kv in ([Management.Automation.CommandMetaData]$_).Parameters.GetEnumerator()) { | ||
@( | ||
. $setOutputStyle -ForegroundColor Verbose | ||
"[$($kv.Value.ParameterType)]" | ||
. $clearOutputStyle | ||
. $setOutputStyle -ForegroundColor Warning | ||
"`$$($kv.Key)" | ||
. $clearOutputStyle | ||
) -join '' | ||
}) -join [Environment]::NewLine | ||
} | ||
} -Wrap -ColorProperty @{ | ||
"Name" = {"Success"} | ||
} | ||
|
||
Write-FormatView -TypeName PSDevOps -Property Name, Description -Width 30, 0 -Wrap -Name Description |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
function Get-PSDevOps | ||
{ | ||
<# | ||
.Synopsis | ||
Gets PSDevOps commands. | ||
.Description | ||
Gets PSDevOps commands. | ||
PSDevOps commands are self-contained scripts that complete end-to-end scenarios. | ||
They are traditionally named with the patterns *.*.ps1 or *.*.*.ps1. | ||
For example: | ||
*.psdevops.ps1 files are used to run commands in PSDevOps. | ||
*.GitHubAction.PSDevOps.ps1 would indicate creating a GitHubAction. | ||
*.tests.ps1 files are used by Pester | ||
*.ezout|ezformat|format|view.ps1 files are used by EZOut | ||
To name a few examples of where the technique is used. | ||
Using Get-PSDevOps will return extended command information and addtional methods. | ||
.Example | ||
Get-PSDevOps # Get *.*.ps1 commands in the current directory | ||
.Example | ||
Get-Module PSDevops | Get-PSDevOps # Gets related commands | ||
#> | ||
param( | ||
# The name of the script. | ||
[Parameter(ValueFromPipelineByPropertyName)] | ||
[string] | ||
$Name, | ||
|
||
# One or more paths to scripts. | ||
# If these paths resolve to directories, all files that match \.(?<Type>.+)\.ps1$ | ||
# If the paths resolve to scripts or commands | ||
[Parameter(ValueFromPipelineByPropertyName)] | ||
[Alias('Fullname')] | ||
[string[]] | ||
$ScriptPath, | ||
|
||
# One or more modules. This can be passed via the pipeline, for example: | ||
# Get-Module PSDevOps | Get-PSDevOps | ||
[Parameter(ValueFromPipelineByPropertyName,ValueFromPipeline)] | ||
[PSModuleInfo[]] | ||
$ModuleInfo, | ||
|
||
# The Regular Expression Pattern used to search for files. | ||
# If a -Pattern is provided, named capture groups in that pattern will become noteproperties of the output object. | ||
# By default: | ||
# (?<ScriptSubtype>\.\w+.)?\.(?<ScriptType>\w+)\.ps1$ | ||
# This roughly translates as: | ||
# Any *.*.ps1 file | ||
# The Named Capture 'Type' the type of .ps1 | ||
# The Optional Named Capture, Subtype, will match an additional '.Something' | ||
[string] | ||
$Pattern = "(?<ScriptSubtype>\.\w+.)?\.(?<ScriptType>\w+)\.ps1$", | ||
|
||
# If set, will search directories recursively. | ||
[switch] | ||
$Recurse | ||
) | ||
|
||
begin { | ||
$regexPattern = [Regex]::new($Pattern, 'IgnoreCase,IgnorePatternWhitespace') | ||
$myModuleName = $MyInvocation.MyCommand.Module.Name | ||
if (-not $script:KnownDevOpsScriptTypes) { | ||
$script:KnownDevOpsScriptTypes = @{} | ||
foreach ($loadedModule in Get-Module) { | ||
$moduleData = $loadedModule.PrivateData.$myModuleName | ||
if (-not $moduleData) { continue } | ||
if ($moduleData.ScriptType -isnot [Hashtable]) { continue } | ||
foreach ($kv in $moduleData.ScriptType.GetEnumerator()) { | ||
$script:KnownDevOpsScriptTypes[$kv.Key] = $kv.Value | ||
} | ||
} | ||
} | ||
} | ||
|
||
process { | ||
$MyModuleName = $MyInvocation.MyCommand.Module.Name | ||
if (-not $ModuleInfo -and -not $ScriptPath) { | ||
$ModuleInfo = | ||
@(foreach ($mod in Get-Module) { | ||
if ($MyModuleName -and ( | ||
($mod.PrivateData.PSData.Tags -contains $MyModuleName) -or | ||
$mod.PrivateData.$MyModuleName | ||
)) { | ||
$mod | ||
} | ||
}) | ||
} | ||
|
||
if ($ModuleInfo) { | ||
$ScriptPath += try { $ModuleInfo | Split-Path -ErrorAction SilentlyContinue } catch { Write-Verbose "Could not Split-Path for $($ModuleInfo)" } | ||
} | ||
if (-not $ScriptPath) { $ScriptPath += "$pwd" } | ||
$ScriptPath = $ScriptPath | Select-Object -Unique | ||
foreach ($sp in $ScriptPath) { | ||
$resolvedPath = | ||
if ([IO.File]::Exists($sp)) { | ||
$sp | ||
} else { | ||
$ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($sp) # Resolve the path | ||
} | ||
|
||
if (-not $resolvedPath) { continue } # ( if we couldn't, keep moving). | ||
# Since the path exists, it's either a file or a directory. | ||
if ([IO.File]::Exists($resolvedPath)) { # If it's a file | ||
$resolvedPathCmd = # get it as a command, | ||
$ExecutionContext.SessionState.InvokeCommand.GetCommand("$resolvedPath", 'All') | ||
$resolvedPathCmd.pstypenames.clear() | ||
$resolvedPathCmd.pstypenames.add('PSDevOps') # then decorate that command as 'PSDevOps', | ||
$resolvedPathCmd # output, | ||
continue # and continue. | ||
} | ||
|
||
# If it's a directory, recurse matters. Also, .NET will be faster than PowerShell providers | ||
$dir = [IO.DirectoryInfo]"$resolvedPath" | ||
foreach ($fsi in $dir.GetFileSystemInfos("*", [IO.SearchOption][int][bool]$Recurse)) { | ||
$matched = $regexPattern.Match($fsi.Name) | ||
if (-not $matched.Success) { continue } | ||
$resolvedPathCmd = # get it as a command, | ||
$ExecutionContext.SessionState.InvokeCommand.GetCommand($fsi.fullname, 'All') | ||
$resolvedPathCmd.pstypenames.clear() | ||
$resolvedPathCmd.pstypenames.add('PSDevOps') # then decorate that command as 'PSDevOps', | ||
$resolvedPathCmd.pstypenames.add('PSDevOps.Script') | ||
|
||
foreach ($group in $matched.Groups[1..$($matched.Groups.Count -1)]) { | ||
$resolvedPathCmd.psobject.properties.add([PSNoteProperty]::new($group.Name, $group.Value)) | ||
} | ||
|
||
|
||
if ($resolvedPathCmd.ScriptType) { | ||
$resolvedPathCmd.psobject.properties.add( | ||
[PSNoteProperty]::new("ScriptTypeDescription", | ||
$script:KnownDevOpsScriptTypes[$resolvedPathCmd.ScriptType] | ||
)) | ||
} | ||
|
||
$resolvedPathCmd | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.