From d23e3d21ff42263be1ac083275eefce9ac6277f8 Mon Sep 17 00:00:00 2001 From: Gijs Reijn Date: Fri, 8 Nov 2024 11:08:16 +0100 Subject: [PATCH] Initial setup of Set-ResourceReadMe --- .../Microsoft.VSCode.Dsc.psm1 | 33 ++++ utilities/tools/Set-ResourceReadMe.ps1 | 172 ++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 utilities/tools/Set-ResourceReadMe.ps1 diff --git a/resources/Microsoft.VSCode.Dsc/Microsoft.VSCode.Dsc.psm1 b/resources/Microsoft.VSCode.Dsc/Microsoft.VSCode.Dsc.psm1 index c05fe6da..8500fc81 100644 --- a/resources/Microsoft.VSCode.Dsc/Microsoft.VSCode.Dsc.psm1 +++ b/resources/Microsoft.VSCode.Dsc/Microsoft.VSCode.Dsc.psm1 @@ -313,6 +313,39 @@ class VSCodeExtension { [void] Uninstall() { $this.Uninstall($true) } + + static [hashtable] GetResourceInfo() { + return @{ + Description = 'The `VSCodeExtension` DSC Resource allows you to install, update, and remove Visual Studio Code extensions. This resource ensures that the specified Visual Studio Code extension is in the desired state.' + # TODO: Add other fields like Synopsis, Notes, etc. + } + } + + static [hashtable] GetResourcePropertyInfo() { + # TODO: We can add JSON schemas for the properties and additionally allowed values if needed + return @{ + Name = @{ + Description = 'The name of the Visual Studio Code extension to manage.' + Type = 'string' + Required = $true + } + Version = @{ + Description = 'The version of the Visual Studio Code extension to install. If not specified, the latest version will be installed.' + Type = 'string' + Required = $false + } + Exist = @{ + Description = 'Indicates whether the extension should exist. The default value is `$true`.' + Type = 'bool' + Required = $false + } + Insiders = @{ + Description = 'Indicates whether to manage the extension for the Insiders version of Visual Studio Code. The default value is `$false`.' + Type = 'bool' + Required = $false + } + } + } #endregion VSCodeExtension helper functions } #endregion DSCResources diff --git a/utilities/tools/Set-ResourceReadMe.ps1 b/utilities/tools/Set-ResourceReadMe.ps1 new file mode 100644 index 00000000..e432e375 --- /dev/null +++ b/utilities/tools/Set-ResourceReadMe.ps1 @@ -0,0 +1,172 @@ +function Initialize-ResourceFile { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $ModuleName, + + [Parameter(Mandatory = $true)] + [string] $ResourceName, + + [Parameter(Mandatory = $true)] + [string] $Synopsis, + + [Parameter(Mandatory = $true)] + [string] $Description + ) + + $initialContent = @( + '---', + "external help file: $ModuleName-Help.xml", + "Module Name: $ModuleName", + "ms.date: $(Get-Date -Format 'MM/dd/yyyy')", + "online version: $null", + 'schema: 2.0.0', + "title: $ResourceName", + '---', + '', + "# $ResourceName", + '', + '## SYNOPSIS', + '', + $Synopsis, + '', + '## DESCRIPTION', + '', + $Description, + '' + ) | Where-Object { $null -ne $_ } # Filter null values + $readMeFileContent = $initialContent + + return $readMeFileContent +} + +function Get-TypeInstanceFromModule { + param( + [Parameter(Mandatory = $true)] + [string] $ModuleName, + [Parameter(Mandatory = $true)] + [string] $ClassName + ) + $instance = & (Import-Module $ModuleName -PassThru) ([scriptblock]::Create("'$ClassName' -as 'type'")) + return $instance +} + +function Set-ResourcePropertyParameters { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [hashtable] $ParameterFileContent, + + [Parameter(Mandatory = $true)] + [object[]] $FileContent + ) + + $parameterSection = @( + '## PARAMETERS', + '', + '| **Parameter** | **Attribute** | **DataType** | **Description** | **Allowed values** |', + '| :------------ | :------------ | :----------- | :-------------- | :----------------- |' + ) + + $ParameterFileContent.GetEnumerator() | ForEach-Object { + $Attribute = $_.Value.Required ? 'Mandatory' : 'Optional' + $DataType = $_.Value.Type + $Description = $_.Value.Description + $AllowedValues = $null # TOCO: Figure a way to get allowed values + $parameterSection += '| {0} | {1} | {2} | {3} | {4} |' -f $_.Key, $Attribute, $DataType, $Description, $AllowedValues + } + + $FileContent += $parameterSection + return $FileContent +} + +function Set-ResourceReadme { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $true)] + [string] $ResourceFilePath, + + [Parameter(Mandatory = $false)] + [string] $ReadMeFilePath = (Join-Path (Split-Path $ResourceFilePath -Parent) 'Help'), + + [Parameter(Mandatory = $false)] + [ValidateSet( + 'Parameters' + )] + [string[]] $SectionsToRefresh = @( + 'Parameters' + ) + ) + + # Check resource file Path + $ResourceFilePath = Resolve-Path -Path $ResourceFilePath -ErrorAction Stop + + if (-not (Test-Path $ResourceFilePath -PathType 'Leaf')) { + throw "[$ResourceFilePath] is no valid file path." + } + + # Check the resources that are exported + $moduleManifest = Import-PowerShellDataFile -Path ($ResourceFilePath.Replace('.psm1', '.psd1')) + $moduleName = $moduleManifest.RootModule.Replace('.psm1', '') + $resources = $moduleManifest.DscResourcesToExport + $resources | ForEach-Object { Write-Verbose -Message ('Resource: {0}' -f $_) } + + # TODO: Grab manual notes if needed + + foreach ($resource in $resources) { + $docFile = Join-Path -Path $ReadMeFilePath -ChildPath ('{0}.md' -f $resource) + + $resourceInstance = Get-TypeInstanceFromModule -ModuleName $ResourceFilePath -ClassName $resource + $dscResourceInstance = $resourceInstance::new() + $t = $dscResourceInstance.GetType() + + $resourceInfoMethod = $t.GetMethod('GetResourceInfo') + if ($null -eq $resourceInfoMethod) { + Write-Warning -Message ('Resource [{0}] does not have a GetResourceInfo method.' -f $resource) + continue + } + + $resourceInfo = $resourceInfoMethod.Invoke($null, $null) + + $resourcePropertyInfoMethod = $t.GetMethod('GetResourcePropertyInfo') + if ($null -eq $resourcePropertyInfoMethod) { + Write-Warning -Message ('Resource [{0}] does not have a GetResourcePropertyInfo method.' -f $resource) + continue + } + + $resourcePropertyInfo = $resourcePropertyInfoMethod.Invoke($null, $null) + + # Initialize the resource file + $inputObject = @{ + ModuleName = $moduleName + ResourceName = $resource + Synopsis = $resourceInfo.Description + Description = $resourceInfo.Description + } + $fileContent = Initialize-ResourceFile @inputObject + + # =============== # + # Set content # + # =============== # + + if ($SectionsToRefresh -contains 'Parameters') { + $fileContent = Set-ResourcePropertyParameters -ParameterFileContent $resourcePropertyInfo -FileContent $fileContent + } + + return $fileContent + + # $commandHelper = [Microsoft.PowerShell.PlatyPS.Model.CommandHelp]::new() + # $commandHelper.Title = $resource + # $commandHelper.Synopsis = $resourceInfo.Description + # $commandHelper.Description = ($resourceInfo.Description + "`n`n## PARAMETERS`n`n" + ($parameterSection -join "`n")) + # $commandHelper.Metadata = [ordered]@{ + # 'external help file' = ('{0}-Help.xml' -f $moduleManifest.RootModule) + # 'Module Name' = 'test' + # 'ms.date' = (Get-Date).ToString('MM/dd/yyyy') + # 'online version' = $null + # schema = '2.0.0' + # title = $resource + # } + } +}