Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/actions/test/nix/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,48 @@ runs:
with:
global-json-file: ./global.json

- name: Set Package Name by Platform
id: set_package_name
shell: pwsh
run: |-
Import-Module ./.github/workflows/GHWorkflowHelper/GHWorkflowHelper.psm1
$platform = $env:RUNNER_OS
Write-Host "Runner platform: $platform"
if ($platform -eq 'Linux') {
$packageName = 'DSC-*-x86_64-linux.tar.gz'
} elseif ($platform -eq 'macOS') {
$packageName = 'DSC-*-x86_64-apple-darwin.tar.gz'
} else {
throw "Unsupported platform: $platform"
}
Set-GWVariable -Name "DSC_PACKAGE_NAME" -Value $packageName
- name: Get Latest DSC Package Version
shell: pwsh
run: |-
Import-Module ./.github/workflows/GHWorkflowHelper/GHWorkflowHelper.psm1
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/Dsc/releases"
$latestRelease = $releases | Where-Object { $v = $_.name.trim("v"); $semVer = [System.Management.Automation.SemanticVersion]::new($v); if ($semVer.Major -eq 3 -and $semVer.Minor -ge 2) { $_ } } | Select-Object -First 1
$latestVersion = $latestRelease.tag_name.TrimStart("v")
Write-Host "Latest DSC Version: $latestVersion"
$packageName = "$env:DSC_PACKAGE_NAME"
Write-Host "Package Name: $packageName"
$downloadUrl = $latestRelease.assets | Where-Object { $_.name -like "*$packageName*" } | Select-Object -First 1 | Select-Object -ExpandProperty browser_download_url
Write-Host "Download URL: $downloadUrl"
$tempPath = Get-GWTempPath
Invoke-RestMethod -Uri $downloadUrl -OutFile "$tempPath/DSC.tar.gz" -Verbose
New-Item -ItemType Directory -Path "$tempPath/DSC" -Force -Verbose
tar xvf "$tempPath/DSC.tar.gz" -C "$tempPath/DSC"
$dscRoot = "$tempPath/DSC"
Write-Host "DSC Root: $dscRoot"
Set-GWVariable -Name "DSC_ROOT" -Value $dscRoot
- name: Bootstrap
shell: pwsh
run: |-
Expand Down
20 changes: 20 additions & 0 deletions .github/actions/test/windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ runs:
with:
global-json-file: .\global.json

- name: Get Latest DSC Package Version
shell: pwsh
run: |-
Import-Module .\.github\workflows\GHWorkflowHelper\GHWorkflowHelper.psm1
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/Dsc/releases"
$latestRelease = $releases | Where-Object { $v = $_.name.trim("v"); $semVer = [System.Management.Automation.SemanticVersion]::new($v); if ($semVer.Major -eq 3 -and $semVer.Minor -ge 2) { $_ } } | Select-Object -First 1
$latestVersion = $latestRelease.tag_name.TrimStart("v")
Write-Host "Latest DSC Version: $latestVersion"

$downloadUrl = $latestRelease.assets | Where-Object { $_.name -like "DSC-*-x86_64-pc-windows-msvc.zip" } | Select-Object -First 1 | Select-Object -ExpandProperty browser_download_url
Write-Host "Download URL: $downloadUrl"
$tempPath = Get-GWTempPath
Invoke-RestMethod -Uri $downloadUrl -OutFile "$tempPath\DSC.zip"

$null = New-Item -ItemType Directory -Path "$tempPath\DSC" -Force
Expand-Archive -Path "$tempPath\DSC.zip" -DestinationPath "$tempPath\DSC" -Force
$dscRoot = "$tempPath\DSC"
Write-Host "DSC Root: $dscRoot"
Set-GWVariable -Name "DSC_ROOT" -Value $dscRoot

- name: Bootstrap
shell: powershell
run: |-
Expand Down
126 changes: 126 additions & 0 deletions dsc/pwsh.profile.dsc.resource.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"description": "Manage PowerShell profiles.",
"tags": [
"Linux",
"Windows",
"macOS",
"PowerShell"
],
"type": "Microsoft.PowerShell/Profile",
"version": "0.1.0",
"get": {
"executable": "pwsh",
"args": [
"-NoLogo",
"-NonInteractive",
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"./pwsh.profile.resource.ps1",
"-operation",
"get"
],
"input": "stdin"
},
"set": {
"executable": "pwsh",
"args": [
"-NoLogo",
"-NonInteractive",
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"./pwsh.profile.resource.ps1",
"-operation",
"set"
],
"input": "stdin"
},
"export": {
"executable": "pwsh",
"args": [
"-NoLogo",
"-NonInteractive",
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"./pwsh.profile.resource.ps1",
"-operation",
"export"
],
"input": "stdin"
},
"exitCodes": {
"0": "Success",
"1": "Error",
"2": "Input not supported for export operation"
},
"schema": {
"embedded": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Profile",
"description": "Manage PowerShell profiles.",
"type": "object",
"unevaluatedProperties": false,
"required": [
"profileType"
],
"properties": {
"profileType": {
"type": "string",
"title": "Profile Type",
"description": "Defines which profile to manage. Valid values are: 'AllUsersCurrentHost', 'AllUsersAllHosts', 'CurrentUserAllHosts', and 'CurrentUserCurrentHost'.",
"enum": [
"AllUsersCurrentHost",
"AllUsersAllHosts",
"CurrentUserAllHosts",
"CurrentUserCurrentHost"
]
},
"profilePath": {
"title": "Profile Path",
"description": "The full path to the profile file.",
"type": "string",
"readOnly": true
},
"content": {
"title": "Content",
"description": "Defines the content of the profile. If you don't specify this property, the resource doesn't manage the file contents. If you specify this property as an empty string, the resource removes all content from the file. If you specify this property as a non-empty string, the resource sets the file contents to the specified string. The resources retains newlines from this property without any modification.",
"type": "string"
},
"_exist": {
"$ref": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/exist.json"
},
"_name": {
"$ref": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/name.json"
}
},
"$defs": {
"https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/exist.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/exist.json",
"title": "Instance should exist",
"description": "Indicates whether the DSC resource instance should exist.",
"type": "boolean",
"default": true,
"enum": [
false,
true
]
},
"https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/name.json": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/properties/name.json",
"title": "Exported instance name",
"description": "Returns a generated name for the resource instance from an export operation.",
"readOnly": true,
"type": "string"
}
}
}
}
}
179 changes: 179 additions & 0 deletions dsc/pwsh.profile.resource.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
## Copyright (c) Microsoft Corporation. All rights reserved.
## Licensed under the MIT License.

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateSet('get', 'set', 'export')]
[string]$Operation,
[Parameter(ValueFromPipeline)]
[string[]]$UserInput
)

Begin {
enum ProfileType {
AllUsersCurrentHost
AllUsersAllHosts
CurrentUserAllHosts
CurrentUserCurrentHost
}

function New-PwshResource {
param(
[Parameter(Mandatory = $true)]
[ProfileType] $ProfileType,

[Parameter(ParameterSetName = 'WithContent')]
[string] $Content,

[Parameter(ParameterSetName = 'WithContent')]
[bool] $Exist
)

# Create the PSCustomObject with properties
$resource = [PSCustomObject]@{
profileType = $ProfileType
content = $null
profilePath = GetProfilePath -profileType $ProfileType
_exist = $false
}

# Add ToJson method
$resource | Add-Member -MemberType ScriptMethod -Name 'ToJson' -Value {
return ([ordered] @{
profileType = $this.profileType
content = $this.content
profilePath = $this.profilePath
_exist = $this._exist
}) | ConvertTo-Json -Compress -EnumsAsStrings
}

# Constructor logic - if Content and Exist parameters are provided (WithContent parameter set)
if ($PSCmdlet.ParameterSetName -eq 'WithContent') {
$resource.content = $Content
$resource._exist = $Exist
} else {
# Default constructor logic - read from file system
$fileExists = Test-Path $resource.profilePath
if ($fileExists) {
$resource.content = Get-Content -Path $resource.profilePath
} else {
$resource.content = $null
}
$resource._exist = $fileExists
}

return $resource
}

function GetProfilePath {
param (
[ProfileType] $profileType
)

$path = switch ($profileType) {
'AllUsersCurrentHost' { $PROFILE.AllUsersCurrentHost }
'AllUsersAllHosts' { $PROFILE.AllUsersAllHosts }
'CurrentUserAllHosts' { $PROFILE.CurrentUserAllHosts }
'CurrentUserCurrentHost' { $PROFILE.CurrentUserCurrentHost }
}

return $path
}

function ExportOperation {
$allUserCurrentHost = New-PwshResource -ProfileType 'AllUsersCurrentHost'
$allUsersAllHost = New-PwshResource -ProfileType 'AllUsersAllHosts'
$currentUserAllHost = New-PwshResource -ProfileType 'CurrentUserAllHosts'
$currentUserCurrentHost = New-PwshResource -ProfileType 'CurrentUserCurrentHost'

# Cannot use the ToJson() method here as we are adding a note property
$allUserCurrentHost | Add-Member -NotePropertyName '_name' -NotePropertyValue 'AllUsersCurrentHost' -PassThru | ConvertTo-Json -Compress -EnumsAsStrings
$allUsersAllHost | Add-Member -NotePropertyName '_name' -NotePropertyValue 'AllUsersAllHosts' -PassThru | ConvertTo-Json -Compress -EnumsAsStrings
$currentUserAllHost | Add-Member -NotePropertyName '_name' -NotePropertyValue 'CurrentUserAllHosts' -PassThru | ConvertTo-Json -Compress -EnumsAsStrings
$currentUserCurrentHost | Add-Member -NotePropertyName '_name' -NotePropertyValue 'CurrentUserCurrentHost' -PassThru | ConvertTo-Json -Compress -EnumsAsStrings
}

function GetOperation {
param (
[Parameter(Mandatory = $true)]
$InputResource,
[Parameter()]
[switch] $AsJson
)

$profilePath = GetProfilePath -profileType $InputResource.profileType.ToString()

$actualState = New-PwshResource -ProfileType $InputResource.profileType

$actualState.profilePath = $profilePath

$exists = Test-Path $profilePath

if ($InputResource._exist -and $exists) {
$content = Get-Content -Path $profilePath
$actualState.Content = $content
} elseif ($InputResource._exist -and -not $exists) {
$actualState.Content = $null
$actualState._exist = $false
} elseif (-not $InputResource._exist -and $exists) {
$actualState.Content = Get-Content -Path $profilePath
$actualState._exist = $true
} else {
$actualState.Content = $null
$actualState._exist = $false
}

if ($AsJson) {
return $actualState.ToJson()
} else {
return $actualState
}
}

function SetOperation {
param (
$InputResource
)

$actualState = GetOperation -InputResource $InputResource

if ($InputResource._exist) {
if (-not $actualState._exist) {
$null = New-Item -Path $actualState.profilePath -ItemType File -Force
}

if ($null -ne $InputResource.content) {
Set-Content -Path $actualState.profilePath -Value $InputResource.content
}
} elseif ($actualState._exist) {
Remove-Item -Path $actualState.profilePath -Force
}
}
}
End {
$inputJson = $input | ConvertFrom-Json

if ($inputJson) {
$InputResource = New-PwshResource -ProfileType $inputJson.profileType -Content $inputJson.content -Exist $inputJson._exist
}

switch ($Operation) {
'get' {
GetOperation -InputResource $InputResource -AsJson
}
'set' {
SetOperation -InputResource $InputResource
}
'export' {
if ($inputJson) {
Write-Error "Input not supported for export operation"
exit 2
}

ExportOperation
}
}

exit 0
}
1 change: 1 addition & 0 deletions experimental-feature-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"PSFeedbackProvider",
"PSLoadAssemblyFromNativeCode",
"PSNativeWindowsTildeExpansion",
"PSProfileDSCResource",
"PSSerializeJSONLongEnumAsNumber",
"PSRedirectToVariable",
"PSSubsystemPluginModel"
Expand Down
1 change: 1 addition & 0 deletions experimental-feature-windows.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"PSFeedbackProvider",
"PSLoadAssemblyFromNativeCode",
"PSNativeWindowsTildeExpansion",
"PSProfileDSCResource",
"PSSerializeJSONLongEnumAsNumber",
"PSRedirectToVariable",
"PSSubsystemPluginModel"
Expand Down
Loading
Loading