From b90eea2d88ecd5a773337ef3668fa3fb93c6bb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Mon, 10 Nov 2025 13:42:01 +0100 Subject: [PATCH 01/23] feat(featureFlag): Include to allow managing feature flags --- Test/public/featureflag.test.ps1 | 19 +++++++ include/config.ps1 | 18 +++++-- include/featureflag.ps1 | 89 ++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 Test/public/featureflag.test.ps1 create mode 100644 include/featureflag.ps1 diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 new file mode 100644 index 0000000..6a7eb26 --- /dev/null +++ b/Test/public/featureflag.test.ps1 @@ -0,0 +1,19 @@ +function Test_FeatureFlag_Success{ + Mock_Config + + Invoke-PrivateContext{ + + $ffName = "ff1" + + $result = Test-FeatureFlag -Key $ffName + Assert-IsFalse -Condition $result + + Set-FeatureFlag $ffName + $result = Test-FeatureFlag -Key $ffName + Assert-IsTrue -Condition $result + + Clear-FeatureFlag $ffName + $result = Test-FeatureFlag -Key $ffName + Assert-IsFalse -Condition $result + } +} \ No newline at end of file diff --git a/include/config.ps1 b/include/config.ps1 index c2ecd07..228a1f7 100644 --- a/include/config.ps1 +++ b/include/config.ps1 @@ -42,7 +42,7 @@ function GetConfigFile { return $path } -function Test-Configuration { +function Test-ConfigurationFile { [CmdletBinding()] param( [Parameter(Position = 0)][string]$Key = "config" @@ -59,9 +59,16 @@ function Get-Configuration { [Parameter(Position = 0)][string]$Key = "config" ) + # Check for cached configuration + $configVar = Get-Variable -scope Script -Name "config-$Key" -ErrorAction SilentlyContinue + if($configVar){ + return $configVar + } + + # No cached configuration; read from file $path = GetConfigFile -Key $Key - if(-Not (Test-Configuration -Key $Key)){ + if(-Not (Test-ConfigurationFile -Key $Key)){ return $null } @@ -78,7 +85,7 @@ function Get-Configuration { function Save-Configuration { [CmdletBinding()] param( - [Parameter(Position = 0)][string]$Key = "config", + [Parameter()][string]$Key = "config", [Parameter(Mandatory = $true, Position = 1)][Object]$Config ) @@ -91,6 +98,9 @@ function Save-Configuration { Write-Warning "Error saving configuration ($Key) to file: $($path). $($_.Exception.Message)" return $false } + finally{ + Remove-Variable -Scope Script -Name "config-$Key" -ErrorAction SilentlyContinue + } return $true } @@ -209,3 +219,5 @@ Export-ModuleMember -Function $NewName + + diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 new file mode 100644 index 0000000..9c14490 --- /dev/null +++ b/include/featureflag.ps1 @@ -0,0 +1,89 @@ +# Feature Flag +# +# Feature Flags management module +# +# Include design description +# This module depends on Config Include +# This module will allow set Feature Flags to the module to quicker release +# features with less risk +# + + +function Get-FeatureFlags{ + [CmdletBinding()] + param() + + $config = Get-Configuration + + if(! $config){ + return @{} + } + + if(! $config.FeatureFlags){ + $config.FeatureFlags = @{} + } + + return $config.FeatureFlags +} + +function Save-FeatureFlags{ + [CmdletBinding()] + param( + [Parameter(Mandatory,Position=0)][hashtable]$FeatureFlags + ) + + $config = Get-Configuration + + if(! $config){ + $config = @{} + } + + if(! $config.FeatureFlags){ + $config.FeatureFlags = @{} + } + + + $config.FeatureFlags = $FeatureFlags + + Save-Configuration -Config $config +} + +function Test-FeatureFlag { + [CmdletBinding()] + param( + [Parameter(Mandatory,Position=0)][string]$Key + ) + + $ffs = Get-FeatureFlags + + $value = $ffs.$key + + return $value -eq $true +} + +function Set-FeatureFlag{ + [CmdletBinding()] + param( + [Parameter(Mandatory,Position=0)][string]$Key, + [Parameter()][bool]$Value = $true + + ) + + $featureFlags = Get-FeatureFlags + + $featureFlags.$Key = $Value + + Save-FeatureFlags $featureFlags + +} + +function Clear-FeatureFlag{ + [CmdletBinding()] + param( + [Parameter(Mandatory,Position=0)][string]$Key + + ) + + Set-FeatureFlag -Key $Key -Value $false + +} \ No newline at end of file From 097fede75fbb9d76e112293d480f574784d7424f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Mon, 10 Nov 2025 14:08:27 +0100 Subject: [PATCH 02/23] test(FeatureFlag): ad testing for FF include --- Test/public/featureflag.test.ps1 | 4 ++-- include/featureflag.ps1 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index 6a7eb26..9650cd6 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -13,7 +13,7 @@ function Test_FeatureFlag_Success{ Assert-IsTrue -Condition $result Clear-FeatureFlag $ffName - $result = Test-FeatureFlag -Key $ffName + $result = tff $ffName Assert-IsFalse -Condition $result } -} \ No newline at end of file +} diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 index 9c14490..e1da303 100644 --- a/include/featureflag.ps1 +++ b/include/featureflag.ps1 @@ -50,6 +50,7 @@ function Save-FeatureFlags{ function Test-FeatureFlag { [CmdletBinding()] + [Alias("tff")] param( [Parameter(Mandatory,Position=0)][string]$Key ) From 439e7e81a809ce2b9601d85ef869643cbddad02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 05:45:20 +0100 Subject: [PATCH 03/23] test(featureFlag): enhance tests for feature flag configuration --- Test/public/featureflag.test.ps1 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index 9650cd6..bafe921 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -4,16 +4,29 @@ function Test_FeatureFlag_Success{ Invoke-PrivateContext{ $ffName = "ff1" + $configFilePath = Invoke-MyCommand -Command "Invoke-IncludeHelperGetConfigRootPath" | Join-Path -ChildPath "config.json" $result = Test-FeatureFlag -Key $ffName Assert-IsFalse -Condition $result - + + # Calling Test-FeatureFlag will create entry on config.FeatureFlags + $config = Get-Content $configFilePath | ConvertFrom-Json -AsHashtable + Assert-IsFalse -Condition $config.FeatureFlags.$ffName + Set-FeatureFlag $ffName $result = Test-FeatureFlag -Key $ffName Assert-IsTrue -Condition $result + + # Set flag adds $true to the config.FeatureFlags + $config = Get-Content $configFilePath| ConvertFrom-Json -AsHashtable + Assert-IsTrue -Condition $config.FeatureFlags.$ffName Clear-FeatureFlag $ffName $result = tff $ffName Assert-IsFalse -Condition $result + + # Clear flag sets the flag to $false in config.FeatureFlags + $config = Get-Content $configFilePath| ConvertFrom-Json -AsHashtable + Assert-IsFalse -Condition $config.FeatureFlags.$ffName } } From c36f12888c9e0a0777267460b6329122e8b1566e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 05:46:31 +0100 Subject: [PATCH 04/23] feat(featureFlag): config all FF called --- include/featureflag.ps1 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 index e1da303..52e602c 100644 --- a/include/featureflag.ps1 +++ b/include/featureflag.ps1 @@ -45,7 +45,11 @@ function Save-FeatureFlags{ $config.FeatureFlags = $FeatureFlags - Save-Configuration -Config $config + $reuslt = Save-Configuration -Config $config + + if(! $reuslt){ + throw "Failed to save Feature Flags" + } } function Test-FeatureFlag { @@ -57,9 +61,14 @@ function Test-FeatureFlag { $ffs = Get-FeatureFlags - $value = $ffs.$key + $value = $ffs.$Key - return $value -eq $true + if($null -eq $value){ + Set-FeatureFlag -Key $Key -Value $false + return $false + } + + return $value } function Set-FeatureFlag{ @@ -87,4 +96,4 @@ function Clear-FeatureFlag{ Set-FeatureFlag -Key $Key -Value $false -} \ No newline at end of file +} From b4ad9e508440888a6304e68bd3ccd992e0fc72f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 07:23:03 +0100 Subject: [PATCH 05/23] refactor(config): rename functions and streamline configuration handling --- Test/public/config.test.ps1 | 39 ++++-------- include/config.ps1 | 114 ++++++++++++------------------------ 2 files changed, 50 insertions(+), 103 deletions(-) diff --git a/Test/public/config.test.ps1 b/Test/public/config.test.ps1 index 453c8a4..725736c 100644 --- a/Test/public/config.test.ps1 +++ b/Test/public/config.test.ps1 @@ -7,38 +7,21 @@ function Test_ConfigInclude{ $result = Get-IncludeHelperConfig Assert-IsNull -Object $result - # Add acount - Add-IncludeHelperConfigAttribute -objectType "Account" -Attribute "acountattribute" + # Add Value String + $value = "Some value" + Set-IncludeHelperConfigValue -Name "TestKey" -Value $value $result = Get-IncludeHelperConfig - Assert-Count -Expected 1 -Presented $result.account_attributes - Assert-Contains -Expected "acountattribute" -Presented $result.account_attributes - Add-IncludeHelperConfigAttribute -objectType "Account" -Attribute "acountattribute2" - $result = Get-IncludeHelperConfig - Assert-Count -Expected 2 -Presented $result.account_attributes - Assert-Contains -Expected "acountattribute" -Presented $result.account_attributes - Assert-Contains -Expected "acountattribute2" -Presented $result.account_attributes + Assert-AreEqual -Expected $value -Presented $result.TestKey - # Add user - Add-IncludeHelperConfigAttribute -objectType "User" -Attribute "userattribute" - $result = Get-IncludeHelperConfig - Assert-Count -Expected 1 -Presented $result.user_attributes - Assert-Contains -Expected "userattribute" -Presented $result.user_attributes - Add-IncludeHelperConfigAttribute -objectType "User" -Attribute "userattribute2" + # Add Value Hashtable + $htable = @{ Key1 = "Value1"; Key2 = "Value2" } + Set-IncludeHelperConfigValue -Name "TestHashtable" -Value $htable $result = Get-IncludeHelperConfig - Assert-Count -Expected 2 -Presented $result.user_attributes - Assert-Contains -Expected "userattribute" -Presented $result.user_attributes - Assert-Contains -Expected "userattribute2" -Presented $result.user_attributes + Assert-AreEqual -Expected $htable.Key1 -Presented $result.TestHashtable.Key1 + Assert-AreEqual -Expected $htable.Key2 -Presented $result.TestHashtable.Key2 - # Add Opportunity - Add-IncludeHelperConfigAttribute -objectType "Opportunity" -Attribute "opportunityattribute" - $result = Get-IncludeHelperConfig - Assert-Count -Expected 1 -Presented $result.opportunity_attributes - Assert-Contains -Expected "opportunityattribute" -Presented $result.opportunity_attributes - Add-IncludeHelperConfigAttribute -objectType "Opportunity" -Attribute "opportunityattribute2" - $result = Get-IncludeHelperConfig - Assert-Count -Expected 2 -Presented $result.opportunity_attributes - Assert-Contains -Expected "opportunityattribute" -Presented $result.opportunity_attributes - Assert-Contains -Expected "opportunityattribute2" -Presented $result.opportunity_attributes + # Previuse value still there + Assert-AreEqual -Expected $value -Presented $result.TestKey } diff --git a/include/config.ps1 b/include/config.ps1 index 228a1f7..09da53f 100644 --- a/include/config.ps1 +++ b/include/config.ps1 @@ -108,7 +108,7 @@ function Save-Configuration { ############ -# Define unique aliases for "MyModule" +# Define unique aliases for "ModuleName" $CONFIG_INVOKE_GET_ROOT_PATH_ALIAS = "$($MODULE_NAME)GetConfigRootPath" $CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-$($MODULE_NAME)GetConfigRootPath" @@ -116,108 +116,72 @@ $CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-$($MODULE_NAME)GetConfigRootPath" Set-MyInvokeCommandAlias -Alias $CONFIG_INVOKE_GET_ROOT_PATH_ALIAS -Command $CONFIG_INVOKE_GET_ROOT_PATH_CMD # Define the function to get the configuration root path -function Invoke-MyModuleGetConfigRootPath { +function Invoke-ModuleNameGetConfigRootPath { [CmdletBinding()] param() $configRoot = GetConfigRootPath return $configRoot } -$function = "Invoke-MyModuleGetConfigRootPath" -$NewName = $function -Replace "MyModule", $MODULE_NAME -Rename-Item -path Function:$Function -NewName $NewName -Export-ModuleMember -Function $NewName +$function = "Invoke-ModuleNameGetConfigRootPath" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} # Extra functions not needed by INCLUDE CONFIG -function Get-MyModuleConfig{ +function Get-ModuleNameConfig{ [CmdletBinding()] param() $config = Get-Configuration return $config -} -$function = "Get-MyModuleConfig" -$NewName = $function -Replace "MyModule", $MODULE_NAME -Rename-Item -path Function:$Function -NewName $NewName -Export-ModuleMember -Function $NewName - -function Save-MyModuleConfig{ - [CmdletBinding()] - param( - [Parameter(Mandatory, ValueFromPipeline, Position = 0)][Object]$Config - ) - - return Save-Configuration -Config $Config -} $function = "Save-MyModuleConfig" -$NewName = $function -Replace "MyModule", $MODULE_NAME -Rename-Item -path Function:$Function -NewName $NewName -Export-ModuleMember -Function $NewName +} +$function = "Get-ModuleNameConfig" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} -function Open-MyModuleConfig{ +function Open-ModuleNameConfig{ [CmdletBinding()] param() $path = GetConfigFile -Key "config" code $path +} +$function = "Open-ModuleNameConfig" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} -} $function = "Open-MyModuleConfig" -$NewName = $function -Replace "MyModule", $MODULE_NAME -Rename-Item -path Function:$Function -NewName $NewName -Export-ModuleMember -Function $NewName - -function Add-MyModuleConfigAttribute{ +function Set-ModuleNameConfigValue{ [CmdletBinding()] param( - [Parameter(Mandatory,Position=0)][ValidateSet("Account", "User", "Opportunity")][string]$objectType, - - [Parameter(Mandatory, ValueFromPipeline, Position = 1)][string]$Attribute - + [Parameter(Mandatory = $true)][string]$Name, + [Parameter(Mandatory = $true)][object]$Value ) - begin{ - $config = Get-Configuration - $configAttribute = ($objectType + "_attributes").ToLower() - - if(-Not $config){ - $config = @{} - } - - if(-Not $config.$configAttribute){ - $config.$configAttribute = @() - } - } + $config = Get-Configuration - process{ - $config.$configAttribute += $Attribute - } - - End{ - $ret = Save-Configuration -Config $config - if(-Not $ret){ - throw "Error saving configuration" - } - - $config = Get-Configuration - Write-Output $config.$configAttribute - + if(-Not $config){ + $config = @{} } -} $function = "Add-MyModuleConfigAttribute" -$NewName = $function -Replace "MyModule", $MODULE_NAME -Rename-Item -path Function:$Function -NewName $NewName -Export-ModuleMember -Function $NewName - - - - - - - - - - - + $config.$Name = $Value + Save-Configuration -Key "config" -Config $config +} +$function = "Set-ModuleNameConfigValue" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} \ No newline at end of file From 21d07959f71582dc993736cd3dcda4b4aef1e4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 07:23:14 +0100 Subject: [PATCH 06/23] refactor(dependencies): streamline function renaming and export logic --- include/MyWrite.ps1 | 32 ++++++++++++++++++++++++-------- include/dependencies.ps1 | 13 ++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/MyWrite.ps1 b/include/MyWrite.ps1 index fe5460e..81f697f 100644 --- a/include/MyWrite.ps1 +++ b/include/MyWrite.ps1 @@ -126,8 +126,12 @@ function Enable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $flag) } -Rename-Item -path Function:Enable-ModuleNameVerbose -NewName "Set-$($MODULE_NAME)Verbose" -Export-ModuleMember -Function "Set-$($MODULE_NAME)Verbose" +$function = "Set-ModuleNameVerbose" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} function Disable-ModuleNameVerbose{ param() @@ -135,8 +139,12 @@ function Disable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $null) } -Rename-Item -path Function:Disable-ModuleNameVerbose -NewName "Clear-$($MODULE_NAME)Verbose" -Export-ModuleMember -Function "Clear-$($MODULE_NAME)Verbose" +$function = "Clear-ModuleNameVerbose" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} function Test-MyDebug { param( @@ -173,8 +181,12 @@ function Enable-ModuleNameDebug{ $moduleDebugVarName = $MODULE_NAME + "_DEBUG" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $flag) } -Rename-Item -path Function:Enable-ModuleNameDebug -NewName "Enable-$($MODULE_NAME)Debug" -Export-ModuleMember -Function "Enable-$($MODULE_NAME)Debug" +$function = "Set-ModuleNameDebug" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} function Disable-ModuleNameDebug { param() @@ -182,8 +194,12 @@ function Disable-ModuleNameDebug { $moduleDebugVarName = $MODULE_NAME + "_DEBUG" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $null) } -Rename-Item -path Function:Disable-ModuleNameDebug -NewName "Disable-$($MODULE_NAME)Debug" -Export-ModuleMember -Function "Disable-$($MODULE_NAME)Debug" +$function = "Clear-ModuleNameDebug" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} function Get-ObjetString { param( diff --git a/include/dependencies.ps1 b/include/dependencies.ps1 index cea9df4..58dd795 100644 --- a/include/dependencies.ps1 +++ b/include/dependencies.ps1 @@ -15,10 +15,9 @@ $MODULE_ROOT_PATH = $PSScriptRoot | split-path -Parent $MODULE_NAME = (Get-ChildItem -Path $MODULE_ROOT_PATH -Filter *.psd1 | Select-Object -First 1).BaseName -$DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME = "Invoke-$($MODULE_NAME)RootPath" # SET MY INVOKE COMMAND ALIAS -Set-MyInvokeCommandAlias -Alias "GetMyModuleRootPath" -Command $DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME +Set-MyInvokeCommandAlias -Alias "GetMyModuleRootPath" -Command "Invoke-$($MODULE_NAME)RootPath" Set-MyInvokeCommandAlias -Alias "CloneRepo" -Command 'git clone {url} {folder}' Set-MyInvokeCommandAlias -Alias "TestGitHubRepo" -Command 'Invoke-WebRequest -Uri "{url}" -Method Head -ErrorAction SilentlyContinue | ForEach-Object { $_.StatusCode -eq 200 }' Set-MyInvokeCommandAlias -Alias "FindModule" -Command 'Find-Module -Name {name} -AllowPrerelease -ErrorAction SilentlyContinue' @@ -28,7 +27,7 @@ Set-MyInvokeCommandAlias -Alias "GetModuleListAvailable" -Command 'Get-Module -N Set-MyInvokeCommandAlias -Alias "ImportModule" -Command 'Import-Module -Name {name} -Scope Global -Verbose:$false -PassThru' # This function will be renamed to avoid collision with other modules -function Invoke-MODULE_NAME_RootPath{ +function Invoke-MyModuleRootPath{ [CmdletBinding()] param() @@ -44,8 +43,12 @@ function Invoke-MODULE_NAME_RootPath{ return $root } -Rename-Item -path Function:Invoke-MODULE_NAME_RootPath -NewName $DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME -Export-ModuleMember -Function $DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME +$function = "Invoke-MyModuleRootPath" +$destFunction = $function -replace "MyModule", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} function Import-Dependency{ [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'High')] From ca575c7b98ee25703e6bf15cb2a3ee52b9f2a055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 07:23:32 +0100 Subject: [PATCH 07/23] refactor(featureFlag): simplify Save-FeatureFlags function logic --- include/featureflag.ps1 | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 index 52e602c..9dac772 100644 --- a/include/featureflag.ps1 +++ b/include/featureflag.ps1 @@ -32,22 +32,9 @@ function Save-FeatureFlags{ [Parameter(Mandatory,Position=0)][hashtable]$FeatureFlags ) - $config = Get-Configuration - - if(! $config){ - $config = @{} - } - - if(! $config.FeatureFlags){ - $config.FeatureFlags = @{} - } - - - $config.FeatureFlags = $FeatureFlags - - $reuslt = Save-Configuration -Config $config + $result = Set-ModuleNameConfigValue -Name "FeatureFlags" -Value $FeatureFlags - if(! $reuslt){ + if(! $result){ throw "Failed to save Feature Flags" } } From e9e36193e6b4174f2c6f039d97df5116a03a4df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 11 Nov 2025 07:26:02 +0100 Subject: [PATCH 08/23] refactor(config): replace Rename-Item with Copy-Item for function aliasing --- include/config.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/config.ps1 b/include/config.ps1 index 09da53f..d94f45f 100644 --- a/include/config.ps1 +++ b/include/config.ps1 @@ -182,6 +182,7 @@ function Set-ModuleNameConfigValue{ $function = "Set-ModuleNameConfigValue" $destFunction = $function -replace "ModuleName", $MODULE_NAME if( -not (Test-Path function:$destFunction )){ - Rename-Item -path Function:$function -NewName $destFunction + # Rename-Item -path Function:$function -NewName $destFunction + Copy-Item -path Function:$function -Destination Function:$destFunction Export-ModuleMember -Function $destFunction } \ No newline at end of file From 306a02531f6ea9e9b2e08a7011eb0bfcd8994d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Wed, 12 Nov 2025 19:53:30 +0100 Subject: [PATCH 09/23] refactor(callAPI): make all functions private --- include/callAPI.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/callAPI.ps1 b/include/callAPI.ps1 index 90b1c3c..f27c0a6 100644 --- a/include/callAPI.ps1 +++ b/include/callAPI.ps1 @@ -61,7 +61,7 @@ function Invoke-GraphQL { throw New-Object system.Exception("Error calling GraphQL",$_.Exception) } -} Export-ModuleMember -Function Invoke-GraphQL +} function Invoke-RestAPI { param( @@ -132,7 +132,7 @@ function Invoke-RestAPI { catch { throw } -} Export-ModuleMember -Function Invoke-RestAPI +} #################################################################################################### @@ -158,7 +158,7 @@ function Get-ApiHost { "Default host $DEFAULT_GH_HOST" | writedebug return $DEFAULT_GH_HOST -} Export-ModuleMember -Function Get-ApiHost +} #################################################################################################### @@ -198,7 +198,7 @@ function Get-ApiToken { } return $result -} Export-ModuleMember -Function Get-ApiToken +} #################################################################################################### @@ -228,3 +228,5 @@ function writedebug{ Write-MyDebug $Message -Section "api" } } + + From eaaac3a221be43ee12fa496a46cfa3e8ce98b854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Wed, 12 Nov 2025 19:54:21 +0100 Subject: [PATCH 10/23] fix(callAPI): Allow calling with OutFile --- include/callAPI.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/callAPI.ps1 b/include/callAPI.ps1 index f27c0a6..f7475a3 100644 --- a/include/callAPI.ps1 +++ b/include/callAPI.ps1 @@ -44,7 +44,9 @@ function Invoke-GraphQL { # Send the request $start = Get-Date ">>> Invoke-RestMethod - $apiUri" | writedebug - $response = Invoke-RestMethod -Uri $apiUri -Method Post -Body $body -Headers $headers -OutFile $OutFile + if([string]::IsNullOrWhiteSpace($OutFile)) + { $response = Invoke-RestMethod -Uri $apiUri -Method Post -Body $body -Headers $headers } + else { $response = Invoke-RestMethod -Uri $apiUri -Method Post -Body $body -Headers $headers -OutFile $OutFile } "<<< Invoke-RestMethod - $apiUri [ $(((Get-Date) - $start).TotalSeconds) seconds]" | writedebug # Trace response @@ -58,6 +60,8 @@ function Invoke-GraphQL { return $response } catch { + "[[THROW]]" | writedebug + $_.Exception.Message | ConvertTo-Json -Depth 100 | writedebug throw New-Object system.Exception("Error calling GraphQL",$_.Exception) } From 2371ddb71dc3d67eef02faaa972bda9511bf4653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:42:23 +0100 Subject: [PATCH 11/23] refactor(config): update MODULE_NAME assignment for clarity --- include/config.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/config.ps1 b/include/config.ps1 index d94f45f..003fa84 100644 --- a/include/config.ps1 +++ b/include/config.ps1 @@ -13,7 +13,9 @@ # # MODULE_NAME -$MODULE_NAME = ($PSScriptRoot | Split-Path -Parent | Get-ChildItem -Filter *.psd1 | Select-Object -First 1).BaseName +$MODULE_NAME_PATH = ($PSScriptRoot | Split-Path -Parent | Get-ChildItem -Filter *.psd1 | Select-Object -First 1) | Split-Path -Parent +$MODULE_NAME = $MODULE_NAME_PATH | Split-Path -LeafBase + if(-Not $MODULE_NAME){ throw "Module name not found. Please check the module structure." } $CONFIG_ROOT = [System.Environment]::GetFolderPath('UserProfile') | Join-Path -ChildPath ".helpers" -AdditionalChildPath $MODULE_NAME, "config" From 40333512abc7a6b450f3f840da73976cc813e3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:42:37 +0100 Subject: [PATCH 12/23] fix(moduleName): rename functions for consistency --- include/MyWrite.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/MyWrite.ps1 b/include/MyWrite.ps1 index 81f697f..084b912 100644 --- a/include/MyWrite.ps1 +++ b/include/MyWrite.ps1 @@ -126,7 +126,7 @@ function Enable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $flag) } -$function = "Set-ModuleNameVerbose" +$function = "Enable-ModuleNameVerbose" $destFunction = $function -replace "ModuleName", $MODULE_NAME if( -not (Test-Path function:$destFunction )){ Rename-Item -path Function:$function -NewName $destFunction @@ -139,7 +139,7 @@ function Disable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $null) } -$function = "Clear-ModuleNameVerbose" +$function = "Disable-ModuleNameVerbose" $destFunction = $function -replace "ModuleName", $MODULE_NAME if( -not (Test-Path function:$destFunction )){ Rename-Item -path Function:$function -NewName $destFunction @@ -181,7 +181,7 @@ function Enable-ModuleNameDebug{ $moduleDebugVarName = $MODULE_NAME + "_DEBUG" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $flag) } -$function = "Set-ModuleNameDebug" +$function = "Enable-ModuleNameDebug" $destFunction = $function -replace "ModuleName", $MODULE_NAME if( -not (Test-Path function:$destFunction )){ Rename-Item -path Function:$function -NewName $destFunction @@ -194,7 +194,7 @@ function Disable-ModuleNameDebug { $moduleDebugVarName = $MODULE_NAME + "_DEBUG" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $null) } -$function = "Clear-ModuleNameDebug" +$function = "Disable-ModuleNameDebug" $destFunction = $function -replace "ModuleName", $MODULE_NAME if( -not (Test-Path function:$destFunction )){ Rename-Item -path Function:$function -NewName $destFunction From 48bc4ec2eab15ea430dca7a7afe129d8dca8656b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:43:03 +0100 Subject: [PATCH 13/23] fix(syncIncludeWithModule): add DestinationModulePath parameter to Add-IncludeToWorkspace calls --- public/syncIncludeWithModule.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/public/syncIncludeWithModule.ps1 b/public/syncIncludeWithModule.ps1 index db2005a..fbe3d0c 100644 --- a/public/syncIncludeWithModule.ps1 +++ b/public/syncIncludeWithModule.ps1 @@ -1,9 +1,11 @@ function Sync-IncludeWithModule{ [CmdletBinding()] - param() + param( + [Parameter()][string]$DestinationModulePath + ) - Get-IncludeFile | Add-IncludeToWorkspace -IfExists + Get-IncludeFile | Add-IncludeToWorkspace -IfExists -DestinationModulePath $DestinationModulePath - Get-IncludeSystemFiles | Add-IncludeToWorkspace -IfExists + Get-IncludeSystemFiles | Add-IncludeToWorkspace -IfExists -DestinationModulePath $DestinationModulePath } Export-ModuleMember -Function Sync-IncludeWithModule \ No newline at end of file From 73233e1a09aead65a567569a06bcc84fed391885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:43:31 +0100 Subject: [PATCH 14/23] fix(callPrivateContext): ensure ModulePath is used if provided --- Test/include/callPrivateContext.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Test/include/callPrivateContext.ps1 b/Test/include/callPrivateContext.ps1 index c9e0ab0..347caae 100644 --- a/Test/include/callPrivateContext.ps1 +++ b/Test/include/callPrivateContext.ps1 @@ -14,10 +14,14 @@ if(-not $MODULE_PATH){ throw "Missing MODULE_PATH variable initialization. Check function Invoke-PrivateContext { param ( [Parameter(Mandatory, Position = 0)] - [scriptblock]$ScriptBlock + [scriptblock]$ScriptBlock, + [string]$ModulePath ) - $modulePath = $MODULE_PATH | Split-Path -Parent + if ([string]::IsNullOrEmpty($ModulePath)) { + $modulePath = $ModulePath | Split-Path -Parent + } + $module = Import-Module -Name $modulePath -PassThru if ($null -eq $module) { From dc8fd0396a41250948ff7544314d4b95f82e1744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:43:51 +0100 Subject: [PATCH 15/23] feat(config): update Mock_Config function to use parameters for paths and module name --- Test/include/config.mock.ps1 | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Test/include/config.mock.ps1 b/Test/include/config.mock.ps1 index f6d5f95..5f5abc6 100644 --- a/Test/include/config.mock.ps1 +++ b/Test/include/config.mock.ps1 @@ -9,29 +9,40 @@ if(-not $MODULE_NAME){ throw "Missing MODULE_NAME varaible initialization. Check for module.helerp.ps1 file." } $MOCK_CONFIG_PATH = "test_config_path" -$CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-$($MODULE_NAME)GetConfigRootPath" +$CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-{modulename}GetConfigRootPath" function Mock_Config{ param( [Parameter(Position=0)][string] $key = "config", - [Parameter(Position=1)][object] $Config + [Parameter(Position=1)][object] $Config, + [Parameter(Position=2)][string] $ModuleName, + [Parameter(Position=3)][string] $MockPath = $MOCK_CONFIG_PATH ) # Remove mock config path if exists - if(Test-Path $MOCK_CONFIG_PATH){ - Remove-Item -Path $MOCK_CONFIG_PATH -ErrorAction SilentlyContinue -Recurse -Force + if(Test-Path $MockPath){ + Remove-Item -Path $fullpath -ErrorAction SilentlyContinue -Recurse -Force } # create mock config path - New-Item -Path $MOCK_CONFIG_PATH -ItemType Directory -Force + New-Item -Path $MockPath -ItemType Directory -Force + + # make full and not relative path + $fullpath = $MockPath | Resolve-Path # if $config is not null save it to a file if($null -ne $Config){ - $configfile = Join-Path -Path $MOCK_CONFIG_PATH -ChildPath "$key.json" + $configfile = Join-Path -Path $fullpath -ChildPath "$key.json" $Config | ConvertTo-Json -Depth 10 | Set-Content $configfile } + if([string]::IsNullOrWhiteSpace($ModuleName)){ + $moduleName = $MODULE_NAME + } + + $invokefunction = $CONFIG_INVOKE_GET_ROOT_PATH_CMD -replace "{modulename}", $moduleName + # Mock invoke call - MockCallToString $CONFIG_INVOKE_GET_ROOT_PATH_CMD -OutString $MOCK_CONFIG_PATH + MockCallToString $invokefunction -OutString $fullpath } \ No newline at end of file From 33b6f706c8d850555d8d6cc32387c7dc66e25044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:44:10 +0100 Subject: [PATCH 16/23] feat(featureflag): add module name handling and feature flag management functions --- include/featureflag.ps1 | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 index 9dac772..e8eb16f 100644 --- a/include/featureflag.ps1 +++ b/include/featureflag.ps1 @@ -8,6 +8,8 @@ # features with less risk # +$MODULE_NAME_PATH = ($PSScriptRoot | Split-Path -Parent | Get-ChildItem -Filter *.psd1 | Select-Object -First 1) | Split-Path -Parent +$MODULE_NAME = $MODULE_NAME_PATH | Split-Path -LeafBase function Get-FeatureFlags{ [CmdletBinding()] @@ -84,3 +86,75 @@ function Clear-FeatureFlag{ Set-FeatureFlag -Key $Key -Value $false } + +function Clear-FeatureFlagsRegistered{ + [cmdletbinding()] + param() + + $rffs = Get-ModuleNameRegisteredFeatureFlags + $ffs = (Get-FeatureFlags).Clone() + + $rffs.deprecated | ForEach-Object { + $ffs.Remove($_) + } + + Save-FeatureFlags $ffs + +} + +###### + +function Get-ModuleNameRegisteredFeatureFlags{ + [cmdletbinding()] + param() + + $ffPath = $MODULE_NAME_PATH | Join-Path -ChildPath "featureflags.json" + + if(! ($ffPath | Test-Path)){ + return + } + + $Json = Get-Content $ffPath + + $ff = $Json | ConvertFrom-Json + + return $ff + +} +$function = "Get-ModuleNameRegisteredFeatureFlags" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Copy-Item -path Function:$function -Destination Function:$destFunction + Export-ModuleMember -Function $destFunction +} + +function Get-ModuleNameFeatureFlags{ + [cmdletbinding()] + param() + + $ffs = Get-FeatureFlags + + return $ffs +} +$function = "Get-ModuleNameFeatureFlags" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} + +function Set-ModuleNameFeatureFlag{ + [cmdletbinding()] + param( + [Parameter(Mandatory,Position=0)][string]$Key, + [Parameter()][bool]$Value = $true + ) + + Set-FeatureFlag -Key $Key -Value $Value +} +$function = "Set-ModuleNameFeatureFlag" +$destFunction = $function -replace "ModuleName", $MODULE_NAME +if( -not (Test-Path function:$destFunction )){ + Rename-Item -path Function:$function -NewName $destFunction + Export-ModuleMember -Function $destFunction +} From 5a084a7e68854ca8c9c85d533aacd2b52a35afff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Thu, 13 Nov 2025 09:44:24 +0100 Subject: [PATCH 17/23] test(featureflag): add tests for registered feature flags and clear deprecated flags --- Test/public/featureflag.test.ps1 | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index bafe921..f24491b 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -30,3 +30,53 @@ function Test_FeatureFlag_Success{ Assert-IsFalse -Condition $config.FeatureFlags.$ffName } } + +function Test_RegisteredFeatureFlags_Success{ + + $modulename = "kk" + + # Create Module + New-ModuleV3 -Name $modulename + $fullpath = $modulename | Resolve-Path + + # update module with required code to run featureflags in it + Sync-IncludeWithModule -DestinationModulePath $fullpath + Get-IncludeFile invokeCommand.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile MyWrite.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile config.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile featureflag.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile module.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + + # Add a fake Registered featureflags configuration + $reg = @{ + deprecated = @( + 'ff1' + 'ff2' + ) + } + $reg | ConvertTo-Json | Out-File -FilePath $fullPath/featureflags.json + + # Import module + Import-Module -Name $fullpath + # Mock config for module kk + Mock_Config -ModuleName $modulename -MockPath "kk_config" + + # Set feature flags in the kk config + Set-kkFeatureFlag ff1 + Set-kkFeatureFlag ff2 -Value $false + Set-kkFeatureFlag ff3 + + # Act - Clear registered deprecated featureflags from config + Invoke-PrivateContext -ModulePath $fullpath { + + Clear-FeatureFlagsRegistered + + } + + # Assert confirm that deprecated flags are removed and ff3 remains + $result = Get-kkFeatureFlags + + Assert-Count -Expected 1 -Presented $result.Keys + Assert-Contains -Expected "ff3" -Presented $result.Keys + +} \ No newline at end of file From 8b432683ea2d6528c02638638ff544f56ea3ca2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 16:33:29 +0100 Subject: [PATCH 18/23] refactor(tests): rename verbose functions for consistency --- Test/public/dependencies.test.ps1 | 20 ++++++++-------- Test/public/parameter.test.helper.test.ps1 | 8 +++---- include/MyWrite.ps1 | 8 +++---- include/dependencies.ps1 | 28 +++++++++++----------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Test/public/dependencies.test.ps1 b/Test/public/dependencies.test.ps1 index 4a50ed0..d580f51 100644 --- a/Test/public/dependencies.test.ps1 +++ b/Test/public/dependencies.test.ps1 @@ -13,11 +13,11 @@ function Test_ImportDepepency_Already_loaded{ Mock_ImportModule -Name $name -Folder $modulesFolder #Act - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $result = Import-Dependency -Name $name -Verbose -Confirm:$false $tt = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose #Assert verbose message Assert-AreEqual -Expected $name -Presented $result.Name @@ -42,11 +42,11 @@ function Test_ImportDepepency_SideBySide{ Mock_ImportModule -Name $name -Folder $modulesFolder # Act - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $result = Import-Dependency -Name $name -Verbose -Confirm:$false $tt = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose # Assert module output Assert-AreEqual -Expected $name -Presented $result.Name @@ -77,11 +77,11 @@ function Test_ImportDepepency_Import_From_Module_Manager{ #Act - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $output = Import-Dependency -Name $name -Verbose -Confirm:$false $result = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose #Assert verbose message Assert-AreEqual -Expected $name -Presented $output.Name @@ -119,11 +119,11 @@ function Test_ImportDepepency_Install_From_Gallery{ MockCallExpression -Command "Install-Module -Name $name -AllowPrerelease -Force" -Expression $expression #Act - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $output = Import-Dependency -Name $name -Verbose -Confirm:$false $result = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose #Assert verbose message Assert-AreEqual -Expected $name -Presented $output.Name @@ -154,11 +154,11 @@ function Test_ImportDependency_Clone_From_GitHub{ Mock_ImportModule -Name $name -Folder $modulesFolder - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $output = Import-Dependency -Name $name -Verbose -Confirm:$false $result = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose #Assert verbose message Assert-AreEqual -Expected $name -Presented $output.Name diff --git a/Test/public/parameter.test.helper.test.ps1 b/Test/public/parameter.test.helper.test.ps1 index 033f488..71fc0a2 100644 --- a/Test/public/parameter.test.helper.test.ps1 +++ b/Test/public/parameter.test.helper.test.ps1 @@ -1,11 +1,11 @@ function Test_parameterstest{ - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $result = Get-DummyFunction @ErrorParameters @WarningParameters @InfoParameters $tt = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose # Assert result Assert-IsTrue -Condition $result @@ -25,11 +25,11 @@ function Test_parameterstest{ function Test_parameterstest_Verbose{ - Set-IncludeHelperVerbose + Enable-IncludeHelperVerbose Start-MyTranscript $result = Get-DummyFunction @ErrorParameters @WarningParameters @InfoParameters -Verbose $tt = Stop-MyTranscript - Clear-IncludeHelperVerbose + Disable-IncludeHelperVerbose # Assert result Assert-IsTrue -Condition $result diff --git a/include/MyWrite.ps1 b/include/MyWrite.ps1 index 94460f0..43173fc 100644 --- a/include/MyWrite.ps1 +++ b/include/MyWrite.ps1 @@ -126,8 +126,8 @@ function Enable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $flag) } -Copy-Item -path Function:Enable-ModuleNameVerbose -Destination Function:"Set-$($MODULE_NAME)Verbose" -Export-ModuleMember -Function "Set-$($MODULE_NAME)Verbose" +Copy-Item -path Function:Enable-ModuleNameVerbose -Destination Function:"Enable-$($MODULE_NAME)Verbose" +Export-ModuleMember -Function "Enable-$($MODULE_NAME)Verbose" function Disable-ModuleNameVerbose{ param() @@ -135,8 +135,8 @@ function Disable-ModuleNameVerbose{ $moduleDebugVarName = $MODULE_NAME + "_VERBOSE" [System.Environment]::SetEnvironmentVariable($moduleDebugVarName, $null) } -Copy-Item -path Function:Disable-ModuleNameVerbose -Destination Function:"Clear-$($MODULE_NAME)Verbose" -Export-ModuleMember -Function "Clear-$($MODULE_NAME)Verbose" +Copy-Item -path Function:Disable-ModuleNameVerbose -Destination Function:"Disable-$($MODULE_NAME)Verbose" +Export-ModuleMember -Function "Disable-$($MODULE_NAME)Verbose" function Test-MyDebug { param( diff --git a/include/dependencies.ps1 b/include/dependencies.ps1 index 3fda4f5..2c1538f 100644 --- a/include/dependencies.ps1 +++ b/include/dependencies.ps1 @@ -27,24 +27,24 @@ Set-MyInvokeCommandAlias -Alias "GetModuleListAvailable" -Command 'Get-Module -N Set-MyInvokeCommandAlias -Alias "ImportModule" -Command 'Import-Module -Name {name} -Scope Global -Verbose:$false -PassThru' # This function will be renamed to avoid collision with other modules -function Invoke-MyModuleRootPath{ - [CmdletBinding()] - param() +# function Invoke-MyModuleRootPath{ +# [CmdletBinding()] +# param() - # We will asume that this include file will be on a public,private or include folder. - $root = $PSScriptRoot | split-path -Parent +# # We will asume that this include file will be on a public,private or include folder. +# $root = $PSScriptRoot | split-path -Parent - # confirm that in root folder we have a psd1 file - $psd1 = Get-ChildItem -Path $root -Filter *.psd1 -Recurse -ErrorAction SilentlyContinue +# # confirm that in root folder we have a psd1 file +# $psd1 = Get-ChildItem -Path $root -Filter *.psd1 -Recurse -ErrorAction SilentlyContinue - if(-Not $psd1){ - throw "Wrong root folder. Not PSD1 file found in [$root]. Modify Invoke-GetMyModuleRootPath to adjust location" - } +# if(-Not $psd1){ +# throw "Wrong root folder. Not PSD1 file found in [$root]. Modify Invoke-GetMyModuleRootPath to adjust location" +# } - return $root -} -Copy-Item -path Function:Invoke-MODULE_NAME_RootPath -Destination Function:$DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME -Export-ModuleMember -Function $DEPENDENCY_GETMYMODULEROOTPATH_INVOKE_FUNCTION_NAME +# return $root +# } +# Copy-Item -path Function:Invoke-MyModuleRootPath -Destination Function:"Invoke-$($MODULE_NAME)RootPath" +# Export-ModuleMember -Function "Invoke-$($MODULE_NAME)RootPath" function Import-Dependency{ [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'High')] From 9d76133a96c861d655b53a4925c4f4cc7b6de9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 16:33:34 +0100 Subject: [PATCH 19/23] fix(include): correct variable reference for module path --- Test/include/callPrivateContext.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/include/callPrivateContext.ps1 b/Test/include/callPrivateContext.ps1 index 347caae..9b9a1e8 100644 --- a/Test/include/callPrivateContext.ps1 +++ b/Test/include/callPrivateContext.ps1 @@ -19,7 +19,7 @@ function Invoke-PrivateContext { ) if ([string]::IsNullOrEmpty($ModulePath)) { - $modulePath = $ModulePath | Split-Path -Parent + $modulePath = $MODULE_PATH | Split-Path -Parent } $module = Import-Module -Name $modulePath -PassThru From 46a6bdc8b4a2c42f9b101c01446a09d5362ac74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 17:19:33 +0100 Subject: [PATCH 20/23] fix(tests): remove loaded module to prevent test interference --- Test/public/featureflag.test.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index f24491b..c67b804 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -79,4 +79,8 @@ function Test_RegisteredFeatureFlags_Success{ Assert-Count -Expected 1 -Presented $result.Keys Assert-Contains -Expected "ff3" -Presented $result.Keys + # Not sure why but if we leave kk loaded it may interfere with other tests + # In particular when calling Resolve-SourceDestinationPath, that calls Get-ModuleRootPath, it will resolve to kk module.helper.ps1 code and not IncludeHelper module one + # resolving to the kk module path and not IncludeHelper module path. + Remove-Module -Name $modulename -Force } \ No newline at end of file From d8cc355115b86afd3963cd8ae4c43317fe949fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 17:19:52 +0100 Subject: [PATCH 21/23] test(ResolveSourceDestinationPath): refactor tests to use Invoke-PrivateContext for isolation --- Test/public/addIncludeToWorkspace.test.ps1 | 69 ++++++++++++---------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/Test/public/addIncludeToWorkspace.test.ps1 b/Test/public/addIncludeToWorkspace.test.ps1 index 3b2d1a5..f9b226e 100644 --- a/Test/public/addIncludeToWorkspace.test.ps1 +++ b/Test/public/addIncludeToWorkspace.test.ps1 @@ -233,37 +233,44 @@ $targetPS1 = $moduleRootPath | Join-Path -ChildPath "public\addIncludeToWorkspac function Test_ResolveSourceDestinationPath{ - $DestinationModuleName = "TargetModule" - $SourceModuleName = "SourceModule" - $LocalModuleName = "LocalModule" - - $IncludeHelperModulePath = (Get-Module -name Includehelper).Path | Split-Path -parent - - New-ModuleV3 -Name $DestinationModuleName ; $DestinationModulePath = $DestinationModuleName | Convert-Path - New-ModuleV3 -Name $SourceModuleName ; $SourceModulePath = $SourceModuleName | Convert-Path - New-ModuleV3 -Name $LocalModuleName ; $LocalModulePath = $LocalModuleName | Convert-Path - - $LocalModuleName | Set-Location - - # Act Null / Null - Soruce:Include to Destination:local - $resultsource,$resultdestination = Resolve-SourceDestinationPath - Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath - Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath - - # Act Source / Null - Source: Path to Destination: local - $resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath - Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath - Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath - - # Act Null / Destination sourceI:Include to Destination: Path - $resultsource,$resultdestination = Resolve-SourceDestinationPath -DestinationModulePath $DestinationModulePath - Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath - Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath - - # Act Sorce / Destination - Source: Path to Destination: Path - $resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath -DestinationModulePath $DestinationModulePath - Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath - Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath + Invoke-PrivateContext { + + $DestinationModuleName = "TargetModule" + $SourceModuleName = "SourceModule" + $LocalModuleName = "LocalModule" + + # Includehelper root folder + $local = $PSScriptRoot + $IncludeHelperModulePath = $local | Split-Path -Parent | Split-Path -Parent + + # TEsting modules + New-ModuleV3 -Name $DestinationModuleName ; $DestinationModulePath = $DestinationModuleName | Convert-Path + New-ModuleV3 -Name $SourceModuleName ; $SourceModulePath = $SourceModuleName | Convert-Path + New-ModuleV3 -Name $LocalModuleName ; $LocalModulePath = $LocalModuleName | Convert-Path + + # Set location to test module + $LocalModuleName | Set-Location + + # Act Null / Null - Soruce:Include to Destination:local + $resultsource,$resultdestination = Resolve-SourceDestinationPath + Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath + Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath + + # Act Source / Null - Source: Path to Destination: local + $resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath + Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath + Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath + + # Act Null / Destination sourceI:Include to Destination: Path + $resultsource,$resultdestination = Resolve-SourceDestinationPath -DestinationModulePath $DestinationModulePath + Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath + Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath + + # Act Sorce / Destination - Source: Path to Destination: Path + $resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath -DestinationModulePath $DestinationModulePath + Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath + Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath + } } From b0159c873796d62c4329942b06acab6316b78cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 18:07:05 +0100 Subject: [PATCH 22/23] test(featureflag): add tests for feature flag functionality and module cleanup --- Test/public/featureflag.test.ps1 | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index c67b804..d7eef9d 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -79,6 +79,55 @@ function Test_RegisteredFeatureFlags_Success{ Assert-Count -Expected 1 -Presented $result.Keys Assert-Contains -Expected "ff3" -Presented $result.Keys + # Not sure why but if we leave kk loaded it may interfere with other tests + # In particular when calling Resolve-SourceDestinationPath, that calls Get-ModuleRootPath, it will resolve to kk module.helper.ps1 code and not IncludeHelper module one + # resolving to the kk module path and not IncludeHelper module path. + Remove-Module -Name $modulename -Force +} + +function Test_RegisteredFeatureFlags__FFFunction_Success{ + + $modulename = "kk" + + # Mock config for module kk + Mock_Config -ModuleName $modulename -MockPath "kk_config" + + # Create Module + New-ModuleV3 -Name $modulename + $fullpath = $modulename | Resolve-Path + + # update module with required code to run featureflags in it + Sync-IncludeWithModule -DestinationModulePath $fullpath + Get-IncludeFile invokeCommand.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile MyWrite.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile config.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile featureflag.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + Get-IncludeFile module.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath + + $functioncode = @" + +function Get-kkString { + if(TFF ff){ + return "ff" + } else { + return "kk" + } +} Export-ModuleMember -Function Get-kkString + +"@ + + $functioncode | Out-File -FilePath ./kk/public/getString.ps1 + + # Import module + Import-Module -Name $fullpath + + Set-kkFeatureFlag ff + $result = Get-kkFeatureFlags + Assert-IsTrue -Condition $result.ff + + $result = Get-kkString + Assert-AreEqual -Expected "ff" -Presented $result + # Not sure why but if we leave kk loaded it may interfere with other tests # In particular when calling Resolve-SourceDestinationPath, that calls Get-ModuleRootPath, it will resolve to kk module.helper.ps1 code and not IncludeHelper module one # resolving to the kk module path and not IncludeHelper module path. From e8c0282c01623bbceee80bb3c2fc44885823ab14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20=28Dibildos=29=20Gonz=C3=A1lez?= Date: Tue, 13 Jan 2026 18:18:10 +0100 Subject: [PATCH 23/23] test(featureflag): enhance tests for feature flag management and cleanup --- Test/public/featureflag.test.ps1 | 9 +++++++-- include/featureflag.ps1 | 10 ++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Test/public/featureflag.test.ps1 b/Test/public/featureflag.test.ps1 index d7eef9d..12cd516 100644 --- a/Test/public/featureflag.test.ps1 +++ b/Test/public/featureflag.test.ps1 @@ -66,11 +66,16 @@ function Test_RegisteredFeatureFlags_Success{ Set-kkFeatureFlag ff2 -Value $false Set-kkFeatureFlag ff3 + # Assert confirm that all 3 flags are set + $result = Get-kkFeatureFlags + Assert-Count -Expected 3 -Presented $result.Keys + Assert-Contains -Expected "ff1" -Presented $result.Keys + Assert-Contains -Expected "ff2" -Presented $result.Keys + Assert-Contains -Expected "ff3" -Presented $result.Keys + # Act - Clear registered deprecated featureflags from config Invoke-PrivateContext -ModulePath $fullpath { - Clear-FeatureFlagsRegistered - } # Assert confirm that deprecated flags are removed and ff3 remains diff --git a/include/featureflag.ps1 b/include/featureflag.ps1 index e8eb16f..677a491 100644 --- a/include/featureflag.ps1 +++ b/include/featureflag.ps1 @@ -2,11 +2,17 @@ # # Feature Flags management module # -# Include design description -# This module depends on Config Include # This module will allow set Feature Flags to the module to quicker release # features with less risk # +# Include design description +# This module depends on Config Include +# Config module will depend on invokeCommand.helper.ps1, MyWrite.ps1, config.ps1, module.helper.ps1 +# +# As you se features keys they will be recorded on a config file. +# Deprecate the FF to have it removed from the config file when the FF is released (aka set functionality to GA with now FF. +# Use Clear-FeatureFlagsRegistered to remove deprecated FF from config + $MODULE_NAME_PATH = ($PSScriptRoot | Split-Path -Parent | Get-ChildItem -Filter *.psd1 | Select-Object -First 1) | Split-Path -Parent $MODULE_NAME = $MODULE_NAME_PATH | Split-Path -LeafBase