diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..c44c24ff --- /dev/null +++ b/.editorconfig @@ -0,0 +1,244 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Code Actions #### + +# Type members +dotnet_hide_advanced_members = false +dotnet_member_insertion_location = with_other_members_of_the_same_kind +dotnet_property_generation_behavior = prefer_throwing_properties + +# Symbol search +dotnet_search_reference_assemblies = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_prefer_system_hash_code = true +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_anonymous_function = true +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_prefer_system_threading_lock = true +csharp_style_namespace_declarations = block_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = false +csharp_new_line_before_else = false +csharp_new_line_before_finally = false +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = none +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/Module/.gitignore b/Module/.gitignore new file mode 100644 index 00000000..d5d52cd3 --- /dev/null +++ b/Module/.gitignore @@ -0,0 +1,389 @@ +Ignore/* +.vs/* +.vscode/* +Examples/Output/* +Releases/* +Artefacts/* +ReleasedUnpacked/* +Sources/.vs +Sources/*/.vs +Sources/*/obj +Sources/*/bin +Sources/*/*/obj +Sources/*/*/bin +Sources/packages/* +Sources/*.DotSettings.user +Sources/*.DotSettings +Lib/Default/* +Lib/Standard/* +Lib/Core/* + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +.vscode/* + +/.idea/ +CLAUDE.md +.claude/* \ No newline at end of file diff --git a/Assets/Images/NewPrepareModule.png b/Module/Assets/Images/NewPrepareModule.png similarity index 100% rename from Assets/Images/NewPrepareModule.png rename to Module/Assets/Images/NewPrepareModule.png diff --git a/Assets/Images/NewPrepareModule1.png b/Module/Assets/Images/NewPrepareModule1.png similarity index 100% rename from Assets/Images/NewPrepareModule1.png rename to Module/Assets/Images/NewPrepareModule1.png diff --git a/Build/Build-Module.ps1 b/Module/Build/Build-Module.ps1 similarity index 96% rename from Build/Build-Module.ps1 rename to Module/Build/Build-Module.ps1 index 233e0d2e..93b1e783 100644 --- a/Build/Build-Module.ps1 +++ b/Module/Build/Build-Module.ps1 @@ -3,9 +3,9 @@ # most modules should be run via PSD1 or by it's name (which in the background uses PD1) # This version is for local building -# We need to rmeove library before we start, as it may contain old files, which will be in use once PSD1 loads +# We need to remove library before we start, as it may contain old files, which will be in use once PSD1 loads # This is only required for PSPublisModule, as it's the only module that is being built by itself -Remove-Item -Path "C:\Support\GitHub\PSPublishModule\Lib" -Recurse -Force -ErrorAction SilentlyContinue +Remove-Item -Path "C:\Support\GitHub\PSPublishModule\Module\Lib" -Recurse -Force -ErrorAction SilentlyContinue Import-Module "$PSScriptRoot\..\PSPublishModule.psd1" -Force @@ -33,6 +33,7 @@ Build-Module -ModuleName 'PSPublishModule' { New-ConfigurationModule -Type RequiredModule -Name 'powershellget' -Guid 'Auto' -Version 'Latest' New-ConfigurationModule -Type RequiredModule -Name 'PSScriptAnalyzer' -Guid 'Auto' -Version 'Latest' New-ConfigurationModule -Type RequiredModule -Name 'Pester' -Version Auto -Guid Auto + New-ConfigurationModule -Type RequiredModule -Name 'Microsoft.PowerShell.PSResourceGet' -Guid 'Auto' -Version 'Latest' # Add external module dependencies, using loop for simplicity New-ConfigurationModule -Type ExternalModule -Name @( @@ -118,7 +119,7 @@ Build-Module -ModuleName 'PSPublishModule' { SkipBuiltinReplacements = $true # required for Cmdlet/Alias functionality - NETProjectPath = "$PSScriptRoot\..\Sources\PSPublishModule" + NETProjectPath = "$PSScriptRoot\..\..\PSPublishModule" ResolveBinaryConflicts = $true ResolveBinaryConflictsName = 'PSPublishModule' NETProjectName = 'PSPublishModule' diff --git a/Build/Build-ModuleLegacy.ps1 b/Module/Build/Build-ModuleLegacy.ps1 similarity index 100% rename from Build/Build-ModuleLegacy.ps1 rename to Module/Build/Build-ModuleLegacy.ps1 diff --git a/Build/Update-Version.ps1 b/Module/Build/Update-Version.ps1 similarity index 100% rename from Build/Update-Version.ps1 rename to Module/Build/Update-Version.ps1 diff --git a/Data/Example-CHANGELOG.MD b/Module/Data/Example-CHANGELOG.MD similarity index 100% rename from Data/Example-CHANGELOG.MD rename to Module/Data/Example-CHANGELOG.MD diff --git a/Data/Example-Gitignore.txt b/Module/Data/Example-Gitignore.txt similarity index 100% rename from Data/Example-Gitignore.txt rename to Module/Data/Example-Gitignore.txt diff --git a/Data/Example-LicenseMIT.txt b/Module/Data/Example-LicenseMIT.txt similarity index 100% rename from Data/Example-LicenseMIT.txt rename to Module/Data/Example-LicenseMIT.txt diff --git a/Data/Example-ModuleBuilder.txt b/Module/Data/Example-ModuleBuilder.txt similarity index 100% rename from Data/Example-ModuleBuilder.txt rename to Module/Data/Example-ModuleBuilder.txt diff --git a/Data/Example-ModulePSD1.txt b/Module/Data/Example-ModulePSD1.txt similarity index 100% rename from Data/Example-ModulePSD1.txt rename to Module/Data/Example-ModulePSD1.txt diff --git a/Data/Example-ModulePSM1.txt b/Module/Data/Example-ModulePSM1.txt similarity index 100% rename from Data/Example-ModulePSM1.txt rename to Module/Data/Example-ModulePSM1.txt diff --git a/Data/Example-ModuleTests.txt b/Module/Data/Example-ModuleTests.txt similarity index 100% rename from Data/Example-ModuleTests.txt rename to Module/Data/Example-ModuleTests.txt diff --git a/Data/Example-README.MD b/Module/Data/Example-README.MD similarity index 100% rename from Data/Example-README.MD rename to Module/Data/Example-README.MD diff --git a/Docs/Convert-ProjectEncoding.md b/Module/Docs/Convert-ProjectEncoding.md similarity index 100% rename from Docs/Convert-ProjectEncoding.md rename to Module/Docs/Convert-ProjectEncoding.md diff --git a/Docs/Convert-ProjectLineEnding.md b/Module/Docs/Convert-ProjectLineEnding.md similarity index 100% rename from Docs/Convert-ProjectLineEnding.md rename to Module/Docs/Convert-ProjectLineEnding.md diff --git a/Docs/Export-CertificateForNuGet.md b/Module/Docs/Export-CertificateForNuGet.md similarity index 100% rename from Docs/Export-CertificateForNuGet.md rename to Module/Docs/Export-CertificateForNuGet.md diff --git a/Docs/Get-MissingFunctions.md b/Module/Docs/Get-MissingFunctions.md similarity index 60% rename from Docs/Get-MissingFunctions.md rename to Module/Docs/Get-MissingFunctions.md index 3ba176fd..78c9387e 100644 --- a/Docs/Get-MissingFunctions.md +++ b/Module/Docs/Get-MissingFunctions.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Get-MissingFunctions ## SYNOPSIS -{{ Fill in the Synopsis }} +Analyzes a script or scriptblock and reports functions it calls that are not present. ## SYNTAX @@ -19,36 +19,48 @@ Get-MissingFunctions [[-FilePath] ] [[-Code] ] [[-Functions ``` ## DESCRIPTION -{{ Fill in the Description }} +Scans the provided file path or scriptblock, detects referenced commands, filters them down to +function calls, and returns a summary or the raw helper function definitions that can be inlined. +When -ApprovedModules is specified, helper definitions are only taken from those modules; otherwise +only the list is returned. +Use this to build self-contained scripts by discovering dependencies. ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +Get-MissingFunctions -FilePath .\Build\Manage-Module.ps1 -Summary +Returns a list of functions used by the script. ``` -{{ Add example description here }} +### EXAMPLE 2 +``` +$sb = { Invoke-ModuleBuild -ModuleName 'MyModule' } +Get-MissingFunctions -Code $sb -SummaryWithCommands -ApprovedModules 'PSSharedGoods','PSPublishModule' +Returns a hashtable with a summary and inlineable helper definitions sourced from approved modules. +``` ## PARAMETERS -### -ApprovedModules -{{ Fill ApprovedModules Description }} +### -FilePath +Path to a script file to analyze for missing function dependencies. +Alias: Path. ```yaml -Type: Array +Type: String Parameter Sets: (All) -Aliases: +Aliases: Path Required: False -Position: 3 +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -Code -{{ Fill Code Description }} +ScriptBlock to analyze instead of a file. +Alias: ScriptBlock. ```yaml Type: ScriptBlock @@ -56,82 +68,82 @@ Parameter Sets: (All) Aliases: ScriptBlock Required: False -Position: 1 +Position: 2 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -FilePath -{{ Fill FilePath Description }} +### -Functions +Known function names to treat as already available (exclude from missing list). ```yaml -Type: String +Type: String[] Parameter Sets: (All) -Aliases: Path +Aliases: Required: False -Position: 0 +Position: 3 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -Functions -{{ Fill Functions Description }} +### -Summary +Return only a flattened summary list of functions used (objects with Name/Source), not inlined definitions. ```yaml -Type: String[] +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False -Position: 2 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -IgnoreFunctions -{{ Fill IgnoreFunctions Description }} +### -SummaryWithCommands +Return a hashtable with Summary (names), SummaryFiltered (objects), and Functions (inlineable text). ```yaml -Type: Array +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False -Position: 4 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -Summary -{{ Fill Summary Description }} +### -ApprovedModules +Module names that are allowed sources for pulling inline helper function definitions. ```yaml -Type: SwitchParameter +Type: Array Parameter Sets: (All) Aliases: Required: False -Position: Named +Position: 4 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -SummaryWithCommands -{{ Fill SummaryWithCommands Description }} +### -IgnoreFunctions +Function names to ignore when computing the missing set. ```yaml -Type: SwitchParameter +Type: Array Parameter Sets: (All) Aliases: Required: False -Position: Named +Position: 5 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -157,11 +169,9 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES +Use with Initialize-PortableScript to emit a self-contained version of a script. ## RELATED LINKS diff --git a/Docs/Get-ModuleInformation.md b/Module/Docs/Get-ModuleInformation.md similarity index 100% rename from Docs/Get-ModuleInformation.md rename to Module/Docs/Get-ModuleInformation.md diff --git a/Docs/Get-ModuleTestFailures.md b/Module/Docs/Get-ModuleTestFailures.md similarity index 100% rename from Docs/Get-ModuleTestFailures.md rename to Module/Docs/Get-ModuleTestFailures.md diff --git a/Docs/Get-PowerShellAssemblyMetadata.md b/Module/Docs/Get-PowerShellAssemblyMetadata.md similarity index 100% rename from Docs/Get-PowerShellAssemblyMetadata.md rename to Module/Docs/Get-PowerShellAssemblyMetadata.md diff --git a/Docs/Get-PowerShellCompatibility.md b/Module/Docs/Get-PowerShellCompatibility.md similarity index 100% rename from Docs/Get-PowerShellCompatibility.md rename to Module/Docs/Get-PowerShellCompatibility.md diff --git a/Docs/Get-ProjectConsistency.md b/Module/Docs/Get-ProjectConsistency.md similarity index 100% rename from Docs/Get-ProjectConsistency.md rename to Module/Docs/Get-ProjectConsistency.md diff --git a/Docs/Get-ProjectEncoding.md b/Module/Docs/Get-ProjectEncoding.md similarity index 100% rename from Docs/Get-ProjectEncoding.md rename to Module/Docs/Get-ProjectEncoding.md diff --git a/Docs/Get-ProjectLineEnding.md b/Module/Docs/Get-ProjectLineEnding.md similarity index 100% rename from Docs/Get-ProjectLineEnding.md rename to Module/Docs/Get-ProjectLineEnding.md diff --git a/Docs/Get-ProjectVersion.md b/Module/Docs/Get-ProjectVersion.md similarity index 100% rename from Docs/Get-ProjectVersion.md rename to Module/Docs/Get-ProjectVersion.md diff --git a/Docs/Initialize-PortableModule.md b/Module/Docs/Initialize-PortableModule.md similarity index 58% rename from Docs/Initialize-PortableModule.md rename to Module/Docs/Initialize-PortableModule.md index 9e059575..b14efddf 100644 --- a/Docs/Initialize-PortableModule.md +++ b/Module/Docs/Initialize-PortableModule.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Initialize-PortableModule ## SYNOPSIS -{{ Fill in the Synopsis }} +Downloads and/or imports a module and its dependencies as a portable set. ## SYNTAX @@ -18,75 +18,91 @@ Initialize-PortableModule [[-Name] ] [[-Path] ] [-Download] [-Im ``` ## DESCRIPTION -{{ Fill in the Description }} +Assists in preparing a portable environment for a module by either downloading it (plus dependencies) +to a specified path, importing those modules from disk, or both. +Generates a convenience script that +imports all discovered module manifests when -Download is used. ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Download +Saves the module and its dependencies into C:\Portable. ``` -{{ Add example description here }} +### EXAMPLE 2 +``` +Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Import +Imports the module and its dependencies from C:\Portable. +``` + +### EXAMPLE 3 +``` +Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Download -Import +Saves and then imports the module and dependencies, and creates a helper script. +``` ## PARAMETERS -### -Download -{{ Fill Download Description }} +### -Name +Name of the module to download/import. +Alias: ModuleName. ```yaml -Type: SwitchParameter +Type: String Parameter Sets: (All) -Aliases: +Aliases: ModuleName Required: False -Position: Named +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -Import -{{ Fill Import Description }} +### -Path +Filesystem path where modules are saved or imported from. +Defaults to the current script root. ```yaml -Type: SwitchParameter +Type: String Parameter Sets: (All) Aliases: Required: False -Position: Named -Default value: None +Position: 2 +Default value: $PSScriptRoot Accept pipeline input: False Accept wildcard characters: False ``` -### -Name -{{ Fill Name Description }} +### -Download +Save the module and its dependencies to the specified path. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) -Aliases: ModuleName +Aliases: Required: False -Position: 0 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -Path -{{ Fill Path Description }} +### -Import +Import the module and its dependencies from the specified path. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False -Position: 1 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` @@ -111,11 +127,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/Initialize-PortableScript.md b/Module/Docs/Initialize-PortableScript.md similarity index 65% rename from Docs/Initialize-PortableScript.md rename to Module/Docs/Initialize-PortableScript.md index a23db3a7..b86163b3 100644 --- a/Docs/Initialize-PortableScript.md +++ b/Module/Docs/Initialize-PortableScript.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Initialize-PortableScript ## SYNOPSIS -{{ Fill in the Synopsis }} +Produces a self-contained script by inlining missing helper function definitions. ## SYNTAX @@ -18,36 +18,38 @@ Initialize-PortableScript [[-FilePath] ] [[-OutputPath] ] [[-App ``` ## DESCRIPTION -{{ Fill in the Description }} +Analyzes the input script for function calls not present in the script itself, pulls helper +definitions from approved modules, and writes a combined output file that begins with those +helper definitions followed by the original script content. +Useful for portable delivery. ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +Initialize-PortableScript -FilePath .\Scripts\Do-Work.ps1 -OutputPath .\Artefacts\Do-Work.Portable.ps1 -ApprovedModules PSSharedGoods +Generates a portable script with helper functions inlined at the top. ``` - -{{ Add example description here }} ## PARAMETERS -### -ApprovedModules -{{ Fill ApprovedModules Description }} +### -FilePath +Path to the source script to analyze and convert. ```yaml -Type: Array +Type: String Parameter Sets: (All) Aliases: Required: False -Position: 2 +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -FilePath -{{ Fill FilePath Description }} +### -OutputPath +Destination path for the generated self-contained script. ```yaml Type: String @@ -55,22 +57,22 @@ Parameter Sets: (All) Aliases: Required: False -Position: 0 +Position: 2 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -OutputPath -{{ Fill OutputPath Description }} +### -ApprovedModules +Module names that are permitted sources for inlined helper functions. ```yaml -Type: String +Type: Array Parameter Sets: (All) Aliases: Required: False -Position: 1 +Position: 3 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -96,11 +98,9 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES +Output encoding is UTF8BOM on PS 7+, UTF8 on PS 5.1 for compatibility. ## RELATED LINKS diff --git a/Docs/Initialize-ProjectManager.md b/Module/Docs/Initialize-ProjectManager.md similarity index 100% rename from Docs/Initialize-ProjectManager.md rename to Module/Docs/Initialize-ProjectManager.md diff --git a/Module/Docs/Install-ProjectDocumentation.md b/Module/Docs/Install-ProjectDocumentation.md new file mode 100644 index 00000000..4b8f775e --- /dev/null +++ b/Module/Docs/Install-ProjectDocumentation.md @@ -0,0 +1,345 @@ +--- +external help file: PSPublishModule-help.xml +Module Name: PSPublishModule +online version: +schema: 2.0.0 +--- + +# Install-ProjectDocumentation + +## SYNOPSIS +Installs bundled module documentation/examples (Internals) to a chosen path. + +## SYNTAX + +### ByName (Default) +``` +Install-ProjectDocumentation [[-Name] ] [-RequiredVersion ] -Path [-Layout ] + [-OnExists ] [-CreateVersionSubfolder] [-Force] [-ListOnly] [-Open] [-NoIntro] + [-ProgressAction ] [-WhatIf] [-Confirm] [] +``` + +### ByModule +``` +Install-ProjectDocumentation [-Module ] [-RequiredVersion ] -Path + [-Layout ] [-OnExists ] [-CreateVersionSubfolder] [-Force] [-ListOnly] [-Open] [-NoIntro] + [-ProgressAction ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +Copies the contents of a module's Internals folder (or the path defined in +PrivateData.PSData.Delivery) to a destination outside of +$env:PSModulePath, including subfolders such as Scripts, Docs, Binaries, Config. +When -IncludeRootReadme/-IncludeRootChangelog/-IncludeRootLicense are enabled in +New-ConfigurationDelivery, root README/CHANGELOG/LICENSE are also copied. + +## EXAMPLES + +### EXAMPLE 1 +``` +Install-ProjectDocumentation -Name AdminManager -Path 'C:\Docs' +``` + +### EXAMPLE 2 +``` +Get-Module -ListAvailable AdminManager | Install-ProjectDocumentation -Path 'D:\\AM' +Installs the highest available version of AdminManager to D:\AM\AdminManager\ +``` + +### EXAMPLE 3 +``` +# Copy into Path\Name only, merge on re-run without overwriting existing files +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -Layout Module +``` + +### EXAMPLE 4 +``` +# Overwrite destination on re-run +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -OnExists Overwrite +``` + +### EXAMPLE 5 +``` +# Dry-run: show what would be copied and where +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -ListOnly -Verbose +``` + +### EXAMPLE 6 +``` +# Copy, suppress intro/links printing, and open README afterwards +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -NoIntro -Open +``` + +### EXAMPLE 7 +``` +# Typical build time configuration +New-ConfigurationInformation -IncludeAll 'Internals\' +New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -DocumentationOrder '01-Intro.md','02-HowTo.md' -IncludeRootReadme -IncludeRootChangelog +``` + +### EXAMPLE 8 +``` +# Direct layout into target folder (no Module/Version subfolders) +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -Layout Direct +``` + +### EXAMPLE 9 +``` +# Copy into C:\\Docs\\EFAdminManager and merge on rerun (only overwrite when -Force) +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -Layout Module -OnExists Merge -Force +``` + +### EXAMPLE 10 +``` +# Overwrite destination entirely on rerun +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -OnExists Overwrite +``` + +### EXAMPLE 11 +``` +# Skip if destination exists +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -OnExists Skip +``` + +### EXAMPLE 12 +``` +# Plan only with verbose output +Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -ListOnly -Verbose +``` + +## PARAMETERS + +### -Name +Module name to install documentation for. +Accepts pipeline by value. + +```yaml +Type: String +Parameter Sets: ByName +Aliases: ModuleName + +Required: False +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -Module +A PSModuleInfo object (e.g., from Get-Module -ListAvailable) to operate on directly. + +```yaml +Type: PSModuleInfo +Parameter Sets: ByModule +Aliases: InputObject, ModuleInfo + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -RequiredVersion +Specific version of the module to target. +If omitted, selects the highest available. + +```yaml +Type: Version +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path +Destination directory where the Internals content will be copied. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Layout +How to lay out the destination path: +- Direct: copy into \ +- Module: copy into \\\\\\ +- ModuleAndVersion (default): copy into \\\\\\\\\\\ + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: ModuleAndVersion +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OnExists +What to do if the destination folder already exists: +- Merge (default): merge files/folders; overwrite files only when -Force is used +- Overwrite: remove the existing destination, then copy fresh +- Skip: do nothing and return the existing destination path +- Stop: throw an error + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Merge +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CreateVersionSubfolder +When set (default), content is placed under '\\\\\\\\\\\'. +If disabled, content is copied directly into '\'. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Overwrite existing files. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ListOnly +Show what would be copied and where, without copying any files. +Returns the +computed destination path(s). +Use -Verbose for details. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Open +After a successful copy, open the README in the destination (if present). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoIntro +Suppress introductory notes and important links printed after installation. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/Docs/Invoke-DotNetReleaseBuild.md b/Module/Docs/Invoke-DotNetReleaseBuild.md similarity index 100% rename from Docs/Invoke-DotNetReleaseBuild.md rename to Module/Docs/Invoke-DotNetReleaseBuild.md diff --git a/Docs/Invoke-ModuleBuild.md b/Module/Docs/Invoke-ModuleBuild.md similarity index 90% rename from Docs/Invoke-ModuleBuild.md rename to Module/Docs/Invoke-ModuleBuild.md index 55821219..d2391e48 100644 --- a/Docs/Invoke-ModuleBuild.md +++ b/Module/Docs/Invoke-ModuleBuild.md @@ -207,7 +207,10 @@ Accept wildcard characters: False ``` ### -IncludeCustomCode -Parameter description +Optional scriptblock executed during staging that can add custom files/folders +to the build. +Use helper functions like Add-Directory/Copy-Item to place extra +content into the temporary module structure before merge/packaging. ```yaml Type: ScriptBlock @@ -222,7 +225,11 @@ Accept wildcard characters: False ``` ### -IncludeToArray -Parameter description +Advanced hashtable form for includes. +Supports keys matching IncludeRoot, +IncludePS1, IncludeAll etc. +Prefer the dedicated parameters unless you need +to pass a single structured object. ```yaml Type: IDictionary @@ -237,7 +244,8 @@ Accept wildcard characters: False ``` ### -LibrariesCore -Parameter description +Alternate relative path for .NET Core-targeted libraries folder. +Default: 'Lib/Core'. ```yaml Type: String @@ -252,7 +260,8 @@ Accept wildcard characters: False ``` ### -LibrariesDefault -Parameter description +Alternate relative path for classic .NET Framework-targeted libraries folder. +Default: 'Lib/Default'. ```yaml Type: String @@ -267,7 +276,8 @@ Accept wildcard characters: False ``` ### -LibrariesStandard -Parameter description +Alternate relative path for .NET Standard-targeted libraries folder. +Default: 'Lib/Standard'. ```yaml Type: String diff --git a/Docs/Invoke-ModuleTestSuite.md b/Module/Docs/Invoke-ModuleTestSuite.md similarity index 100% rename from Docs/Invoke-ModuleTestSuite.md rename to Module/Docs/Invoke-ModuleTestSuite.md diff --git a/Docs/New-ConfigurationArtefact.md b/Module/Docs/New-ConfigurationArtefact.md similarity index 100% rename from Docs/New-ConfigurationArtefact.md rename to Module/Docs/New-ConfigurationArtefact.md diff --git a/Docs/New-ConfigurationBuild.md b/Module/Docs/New-ConfigurationBuild.md similarity index 76% rename from Docs/New-ConfigurationBuild.md rename to Module/Docs/New-ConfigurationBuild.md index 481ccdd5..3c49c8a5 100644 --- a/Docs/New-ConfigurationBuild.md +++ b/Module/Docs/New-ConfigurationBuild.md @@ -14,17 +14,18 @@ Allows to configure build process for the module ``` New-ConfigurationBuild [-Enable] [-DeleteTargetModuleBeforeBuild] [-MergeModuleOnBuild] - [-MergeFunctionsFromApprovedModules] [-SignModule] [-DotSourceClasses] [-DotSourceLibraries] - [-SeparateFileLibraries] [-RefreshPSD1Only] [-UseWildcardForFunctions] [-LocalVersioning] - [-SkipBuiltinReplacements] [-DoNotAttemptToFixRelativePaths] [[-CertificateThumbprint] ] - [[-CertificatePFXPath] ] [[-CertificatePFXBase64] ] [[-CertificatePFXPassword] ] - [[-NETProjectPath] ] [[-NETConfiguration] ] [[-NETFramework] ] - [[-NETProjectName] ] [-NETExcludeMainLibrary] [[-NETExcludeLibraryFilter] ] - [[-NETIgnoreLibraryOnLoad] ] [[-NETBinaryModule] ] [-NETHandleAssemblyWithSameName] - [-NETLineByLineAddType] [-NETBinaryModuleCmdletScanDisabled] [-NETMergeLibraryDebugging] - [-NETResolveBinaryConflicts] [[-NETResolveBinaryConflictsName] ] [-NETBinaryModuleDocumentation] - [-NETDoNotCopyLibrariesRecursively] [[-NETSearchClass] ] [-NETHandleRuntimes] - [-ProgressAction ] [] + [-MergeFunctionsFromApprovedModules] [-SignModule] [-SignIncludeInternals] [-SignIncludeBinaries] + [-SignIncludeExe] [[-SignCustomInclude] ] [[-SignExcludePaths] ] [-DotSourceClasses] + [-DotSourceLibraries] [-SeparateFileLibraries] [-RefreshPSD1Only] [-UseWildcardForFunctions] + [-LocalVersioning] [-SkipBuiltinReplacements] [-DoNotAttemptToFixRelativePaths] + [[-CertificateThumbprint] ] [[-CertificatePFXPath] ] [[-CertificatePFXBase64] ] + [[-CertificatePFXPassword] ] [[-NETProjectPath] ] [[-NETConfiguration] ] + [[-NETFramework] ] [[-NETProjectName] ] [-NETExcludeMainLibrary] + [[-NETExcludeLibraryFilter] ] [[-NETIgnoreLibraryOnLoad] ] [[-NETBinaryModule] ] + [-NETHandleAssemblyWithSameName] [-NETLineByLineAddType] [-NETBinaryModuleCmdletScanDisabled] + [-NETMergeLibraryDebugging] [-NETResolveBinaryConflicts] [[-NETResolveBinaryConflictsName] ] + [-NETBinaryModuleDocumentation] [-NETDoNotCopyLibrariesRecursively] [[-NETSearchClass] ] + [-NETHandleRuntimes] [-ProgressAction ] [] ``` ## DESCRIPTION @@ -86,7 +87,8 @@ Accept wildcard characters: False ``` ### -MergeModuleOnBuild -Parameter description +Merge module on build. +Combines Private/Public/Classes/Enums into a single PSM1 and prepares PSD1 accordingly. ```yaml Type: SwitchParameter @@ -101,7 +103,7 @@ Accept wildcard characters: False ``` ### -MergeFunctionsFromApprovedModules -Parameter description +When merging, also include functions from ApprovedModules referenced by the module. ```yaml Type: SwitchParameter @@ -116,7 +118,11 @@ Accept wildcard characters: False ``` ### -SignModule -Parameter description +Enables code-signing for the built module output. +When enabled alone, only merged +scripts are signed (psm1/psd1/ps1) and Internals are excluded. +Use the SignInclude* +switches to opt-in to additional content. ```yaml Type: SwitchParameter @@ -130,8 +136,95 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -SignIncludeInternals +When signing is enabled, also sign scripts that reside under the Internals folder. +Default: disabled (Internals are skipped). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SignIncludeBinaries +When signing is enabled, include binary files (e.g., .dll, .cat) in signing. +Default: disabled. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SignIncludeExe +When signing is enabled, include .exe files. +Default: disabled. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SignCustomInclude +Overrides the include patterns passed to the signer. +If provided, this replaces +the defaults entirely. +Example: '*.psm1','*.psd1','*.ps1','*.dll'. +Use with +caution; it disables the default safe set. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SignExcludePaths +Additional path substrings to exclude from signing (relative matches). +Example: +'Examples','SomeFolder'. +Internals are excluded by default unless +-SignIncludeInternals is specified. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -DotSourceClasses -Parameter description +Keep classes in a separate dot-sourced file instead of merging them into the main PSM1. ```yaml Type: SwitchParameter @@ -146,7 +239,7 @@ Accept wildcard characters: False ``` ### -DotSourceLibraries -Parameter description +Keep library-loading code in a separate dot-sourced file. ```yaml Type: SwitchParameter @@ -161,7 +254,7 @@ Accept wildcard characters: False ``` ### -SeparateFileLibraries -Parameter description +Write library-loading code into a distinct file and reference it via ScriptsToProcess/DotSource. ```yaml Type: SwitchParameter @@ -176,7 +269,7 @@ Accept wildcard characters: False ``` ### -RefreshPSD1Only -Parameter description +Only regenerate the manifest (PSD1) without rebuilding/merging other artifacts. ```yaml Type: SwitchParameter @@ -191,7 +284,8 @@ Accept wildcard characters: False ``` ### -UseWildcardForFunctions -Parameter description +Export all functions/aliases via wildcard in PSD1. +Useful for debugging non-merged builds. ```yaml Type: SwitchParameter @@ -206,7 +300,7 @@ Accept wildcard characters: False ``` ### -LocalVersioning -Parameter description +Use local versioning (bump PSD1 version on each build without querying PSGallery). ```yaml Type: SwitchParameter @@ -266,7 +360,7 @@ Accept wildcard characters: False ``` ### -CertificateThumbprint -Parameter description +Thumbprint of a code-signing certificate from the local cert store to sign module files. ```yaml Type: String @@ -274,14 +368,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 1 +Position: 3 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -CertificatePFXPath -Parameter description +Path to a PFX containing a code-signing certificate used for signing. ```yaml Type: String @@ -289,14 +383,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 2 +Position: 4 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -CertificatePFXBase64 -Parameter description +Base64 string of a PFX (e.g., provided via CI secrets) used for signing. ```yaml Type: String @@ -304,14 +398,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 3 +Position: 5 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -CertificatePFXPassword -Parameter description +Password for the PFX provided via -CertificatePFXPath or -CertificatePFXBase64. ```yaml Type: String @@ -319,7 +413,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 4 +Position: 6 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -335,14 +429,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 5 +Position: 7 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -NETConfiguration -Parameter description +Build configuration for .NET projects ('Release' or 'Debug'). ```yaml Type: String @@ -350,14 +444,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 6 +Position: 8 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -NETFramework -Parameter description +Target frameworks for .NET build (e.g., 'netstandard2.0','net6.0'). ```yaml Type: String[] @@ -365,7 +459,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 7 +Position: 9 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -381,7 +475,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 8 +Position: 10 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -413,7 +507,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 9 +Position: 11 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -430,7 +524,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 10 +Position: 12 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -449,7 +543,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 11 +Position: 13 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -543,7 +637,7 @@ Parameter Sets: (All) Aliases: ResolveBinaryConflictsName Required: False -Position: 12 +Position: 14 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -590,7 +684,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 13 +Position: 15 Default value: None Accept pipeline input: False Accept wildcard characters: False diff --git a/Docs/New-ConfigurationCommand.md b/Module/Docs/New-ConfigurationCommand.md similarity index 74% rename from Docs/New-ConfigurationCommand.md rename to Module/Docs/New-ConfigurationCommand.md index 8ab0279e..7c9729c5 100644 --- a/Docs/New-ConfigurationCommand.md +++ b/Module/Docs/New-ConfigurationCommand.md @@ -8,7 +8,7 @@ schema: 2.0.0 # New-ConfigurationCommand ## SYNOPSIS -{{ Fill in the Synopsis }} +Defines a command import configuration for the build pipeline. ## SYNTAX @@ -18,24 +18,23 @@ New-ConfigurationCommand [[-ModuleName] ] [[-CommandName] ] ``` ## DESCRIPTION -{{ Fill in the Description }} +Creates a configuration object that specifies a module and one or more command names +to reference during the build process (for discovery, linking, or documentation). ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +New-ConfigurationCommand -ModuleName 'PSSharedGoods' -CommandName 'Write-Text','Remove-EmptyValue' ``` - -{{ Add example description here }} ## PARAMETERS -### -CommandName -{{ Fill CommandName Description }} +### -ModuleName +Name of the module that contains the commands. ```yaml -Type: String[] +Type: String Parameter Sets: (All) Aliases: @@ -46,16 +45,16 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ModuleName -{{ Fill ModuleName Description }} +### -CommandName +One or more command names to reference from the module. ```yaml -Type: String +Type: String[] Parameter Sets: (All) Aliases: Required: False -Position: 0 +Position: 2 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -81,11 +80,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/New-ConfigurationCompatibility.md b/Module/Docs/New-ConfigurationCompatibility.md similarity index 100% rename from Docs/New-ConfigurationCompatibility.md rename to Module/Docs/New-ConfigurationCompatibility.md diff --git a/Module/Docs/New-ConfigurationDelivery.md b/Module/Docs/New-ConfigurationDelivery.md new file mode 100644 index 00000000..c8f312d2 --- /dev/null +++ b/Module/Docs/New-ConfigurationDelivery.md @@ -0,0 +1,389 @@ +--- +external help file: PSPublishModule-help.xml +Module Name: PSPublishModule +online version: +schema: 2.0.0 +--- + +# New-ConfigurationDelivery + +## SYNOPSIS +Configures delivery metadata for bundling and installing internal docs/examples. + +## SYNTAX + +``` +New-ConfigurationDelivery [-Enable] [[-InternalsPath] ] [-IncludeRootReadme] [-IncludeRootChangelog] + [-IncludeRootLicense] [[-ReadmeDestination] ] [[-ChangelogDestination] ] + [[-LicenseDestination] ] [[-ImportantLinks] ] [[-IntroText] ] + [[-UpgradeText] ] [[-IntroFile] ] [[-UpgradeFile] ] [[-RepositoryPaths] ] + [[-RepositoryBranch] ] [[-DocumentationOrder] ] [-ProgressAction ] + [] +``` + +## DESCRIPTION +Adds Delivery options to the PSPublishModule configuration so the build embeds +runtime metadata in the manifest (PrivateData.PSData.Delivery and PrivateData.PSData.Repository) +and so the Internals folder is easy to find post-install by helper cmdlets +such as Install-ModuleDocumentation. + +Typical usage is to call this in your Build\Manage-Module.ps1 alongside +New-ConfigurationInformation -IncludeAll 'Internals\' so that the Internals +directory is physically included in the shipped module and discoverable later. + +## EXAMPLES + +### EXAMPLE 1 +``` +New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -IncludeRootReadme -IncludeRootChangelog +Emits Options.Delivery and causes PrivateData.PSData.Delivery/Repository to be written in the manifest. +``` + +### EXAMPLE 2 +``` +New-ConfigurationInformation -IncludeAll 'Internals\' +PS> New-ConfigurationDelivery -Enable +Minimal configuration that bundles Internals and exposes it to the installer. +``` + +### EXAMPLE 3 +``` +# Include Internals and configure Docs ordering + repo docs +New-ConfigurationInformation -IncludeAll 'Internals\' +New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -DocumentationOrder '01-Intro.md','02-HowTo.md','99-FAQ.md' -RepositoryPaths 'docs' -RepositoryBranch 'main' +# This causes: +# - Internals\Docs to be bundled and shown in the UI in the given order (remaining files alphabetically) +# - Repository Docs folder to be fetched/displayed when -PreferRepository is used, also respecting DocumentationOrder +``` + +### EXAMPLE 4 +``` +# GitHub: configure remote docs +# 1) Set token once (Windows): setx PG_GITHUB_TOKEN "ghp_xxx" +# or call Set-ModuleDocumentation -GitHubToken 'ghp_xxx' +# 2) In your build script, indicate where docs live in the repo +New-ConfigurationDelivery -Enable -RepositoryPaths 'docs' -RepositoryBranch main +# Then on the viewing side: Show-ModuleDocumentation -Name EFAdminManager -PreferRepository +``` + +### EXAMPLE 5 +``` +# Azure DevOps: configure remote docs +# URL form: https://dev.azure.com/{organization}/{project}/_git/{repository} +# PAT scope: Code (Read) +# 1) Set token once (Windows): setx PG_AZDO_PAT "your_pat" +# or call Set-ModuleDocumentation -AzureDevOpsPat 'your_pat' +# 2) In your build script, indicate repo docs path +New-ConfigurationDelivery -Enable -RepositoryPaths 'Docs/en-US' -RepositoryBranch main +# Then on the viewing side: Show-ModuleDocumentation -Name EFAdminManager -PreferRepository +``` + +### EXAMPLE 6 +``` +# Mix Intro/Upgrade from files with ImportantLinks and include LICENSE in both root and Internals +New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -IntroFile 'Docs\\Intro.md' -UpgradeFile 'Docs\\Upgrade.md' -ImportantLinks @( + @{ Title = 'Home'; Url = 'https://contoso.example/docs' }, + @{ Title = 'Issues'; Url = 'https://contoso.example/issues' } +) -IncludeRootLicense -LicenseDestination Both +``` + +### EXAMPLE 7 +``` +# Multiple repository docs roots and custom order +New-ConfigurationDelivery -Enable -RepositoryPaths 'docs','guides' -RepositoryBranch main -DocumentationOrder '01-Intro.md','20-FAQ.md' +``` + +## PARAMETERS + +### -Enable +Enables delivery metadata emission. +If not specified, nothing is emitted. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InternalsPath +Relative path inside the module that contains internal deliverables +(e.g. +'Internals'). +Defaults to 'Internals'. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: Internals +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludeRootReadme +Include module root README.* during installation (if present). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludeRootChangelog +Include module root CHANGELOG.* during installation (if present). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludeRootLicense +Include module root LICENSE.* during installation (if present). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ReadmeDestination +Where to bundle README.* within the built module. +One of: Internals, Root, Both, None. +Default: Internals. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: Internals +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChangelogDestination +Where to bundle CHANGELOG.* within the built module. +One of: Internals, Root, Both, None. +Default: Internals. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: Internals +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LicenseDestination +Where to bundle LICENSE.* within the built module. +One of: Internals, Root, Both, None. +Default: Internals. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: Internals +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImportantLinks +One or more key/value pairs that represent important links to display to the user, +for example @{ Title = 'Docs'; Url = 'https://...' }. + +```yaml +Type: IDictionary[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 5 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IntroText +Text lines shown to users after Install-ModuleDocumentation completes. +Accepts a string array. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 6 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UpgradeText +Text lines with upgrade instructions shown when requested via Show-ModuleDocumentation -Upgrade. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 7 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IntroFile +Relative path (within the module root) to a Markdown/text file to use as the Intro content. +If provided, it is preferred over IntroText for display and is also copied by +Install-ModuleDocumentation. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 8 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UpgradeFile +Relative path (within the module root) to a Markdown/text file to use for Upgrade instructions. +If provided, it is preferred over UpgradeText for display and is also copied by +Install-ModuleDocumentation. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 9 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RepositoryPaths +One or more repository-relative paths (folders) from which to display remote documentation files +directly from the git hosting provider (GitHub/Azure DevOps). +This enables tools such as +PSMaintenance to fetch and present docs straight from the repository when local copies are not +present or when explicitly requested. +Requires PrivateData.PSData.ProjectUri to be set in the manifest. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 10 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RepositoryBranch +Optional branch name to use when fetching remote documentation. +If omitted, providers fall back to +the repository default branch (e.g., main/master). + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 11 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DocumentationOrder +Optional file-name order for Internals\Docs when rendering documentation. +Provide names such as +'Intro.md','HowTo.md','FAQ.md'; files not listed are appended alphabetically. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 12 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +This emits a Type 'Options' object under Options.Delivery so it works with the +existing New-PrepareStructure logic without further changes. + +## RELATED LINKS diff --git a/Docs/New-ConfigurationDocumentation.md b/Module/Docs/New-ConfigurationDocumentation.md similarity index 100% rename from Docs/New-ConfigurationDocumentation.md rename to Module/Docs/New-ConfigurationDocumentation.md diff --git a/Docs/New-ConfigurationExecute.md b/Module/Docs/New-ConfigurationExecute.md similarity index 75% rename from Docs/New-ConfigurationExecute.md rename to Module/Docs/New-ConfigurationExecute.md index 55a75369..5eb5afa6 100644 --- a/Docs/New-ConfigurationExecute.md +++ b/Module/Docs/New-ConfigurationExecute.md @@ -8,7 +8,7 @@ schema: 2.0.0 # New-ConfigurationExecute ## SYNOPSIS -{{ Fill in the Synopsis }} +Reserved placeholder for future execution-time configuration. ## SYNTAX @@ -17,16 +17,17 @@ New-ConfigurationExecute [-ProgressAction ] [ {{ Add example code here }} +### EXAMPLE 1 +``` +New-ConfigurationExecute +Does nothing and returns no output. ``` - -{{ Add example description here }} ## PARAMETERS @@ -50,11 +51,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/New-ConfigurationFileConsistency.md b/Module/Docs/New-ConfigurationFileConsistency.md similarity index 100% rename from Docs/New-ConfigurationFileConsistency.md rename to Module/Docs/New-ConfigurationFileConsistency.md diff --git a/Docs/New-ConfigurationFormat.md b/Module/Docs/New-ConfigurationFormat.md similarity index 71% rename from Docs/New-ConfigurationFormat.md rename to Module/Docs/New-ConfigurationFormat.md index 70741695..6ab6d775 100644 --- a/Docs/New-ConfigurationFormat.md +++ b/Module/Docs/New-ConfigurationFormat.md @@ -8,7 +8,7 @@ schema: 2.0.0 # New-ConfigurationFormat ## SYNOPSIS -{{ Fill in the Synopsis }} +Builds formatting options for code and manifest generation during the build. ## SYNTAX @@ -28,36 +28,44 @@ New-ConfigurationFormat [-ApplyTo] [-EnableFormatting] [[-Sort] {{ Add example code here }} +### EXAMPLE 1 +``` +New-ConfigurationFormat -ApplyTo 'OnMergePSD1','DefaultPSD1' -PSD1Style 'Minimal' +Minimizes PSD1 output during merge and default builds. ``` -{{ Add example description here }} +### EXAMPLE 2 +``` +New-ConfigurationFormat -ApplyTo 'OnMergePSM1' -EnableFormatting -UseConsistentIndentationEnable -UseConsistentIndentationKind space -UseConsistentIndentationIndentationSize 4 +Enables indentation and whitespace rules for merged PSM1. +``` ## PARAMETERS -### -AlignAssignmentStatementCheckHashtable -{{ Fill AlignAssignmentStatementCheckHashtable Description }} +### -ApplyTo +One or more targets to apply formatting to: OnMergePSM1, OnMergePSD1, DefaultPSM1, DefaultPSD1. ```yaml -Type: SwitchParameter +Type: String[] Parameter Sets: (All) Aliases: -Required: False -Position: Named +Required: True +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -AlignAssignmentStatementEnable -{{ Fill AlignAssignmentStatementEnable Description }} +### -EnableFormatting +When set, enables formatting for the chosen ApplyTo targets even if no specific rule switches are provided. ```yaml Type: SwitchParameter @@ -66,29 +74,29 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -ApplyTo -{{ Fill ApplyTo Description }} +### -Sort +Optional ordering hint for internal processing. +Accepts None, Asc, or Desc. ```yaml -Type: String[] +Type: String Parameter Sets: (All) Aliases: -Accepted values: OnMergePSM1, OnMergePSD1, DefaultPSM1, DefaultPSD1 -Required: True -Position: 0 +Required: False +Position: 2 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -EnableFormatting -{{ Fill EnableFormatting Description }} +### -RemoveComments +Remove comments in the formatted output. ```yaml Type: SwitchParameter @@ -97,29 +105,28 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PSD1Style -{{ Fill PSD1Style Description }} +### -RemoveEmptyLines +Remove empty lines while preserving readability. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: -Accepted values: Minimal, Native Required: False -Position: 5 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceCloseBraceEnable -{{ Fill PlaceCloseBraceEnable Description }} +### -RemoveAllEmptyLines +Remove all empty lines (more aggressive than RemoveEmptyLines). ```yaml Type: SwitchParameter @@ -128,13 +135,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceCloseBraceIgnoreOneLineBlock -{{ Fill PlaceCloseBraceIgnoreOneLineBlock Description }} +### -RemoveCommentsInParamBlock +Remove comments within the param() block. ```yaml Type: SwitchParameter @@ -143,13 +150,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceCloseBraceNewLineAfter -{{ Fill PlaceCloseBraceNewLineAfter Description }} +### -RemoveCommentsBeforeParamBlock +Remove comments that appear immediately before the param() block. ```yaml Type: SwitchParameter @@ -158,13 +165,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceCloseBraceNoEmptyLineBefore -{{ Fill PlaceCloseBraceNoEmptyLineBefore Description }} +### -PlaceOpenBraceEnable +Enable PSPlaceOpenBrace rule and configure its behavior. ```yaml Type: SwitchParameter @@ -173,13 +180,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceOpenBraceEnable -{{ Fill PlaceOpenBraceEnable Description }} +### -PlaceOpenBraceOnSameLine +For PSPlaceOpenBrace: place opening brace on the same line. ```yaml Type: SwitchParameter @@ -188,13 +195,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceOpenBraceIgnoreOneLineBlock -{{ Fill PlaceOpenBraceIgnoreOneLineBlock Description }} +### -PlaceOpenBraceNewLineAfter +For PSPlaceOpenBrace: enforce a new line after the opening brace. ```yaml Type: SwitchParameter @@ -203,13 +210,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceOpenBraceNewLineAfter -{{ Fill PlaceOpenBraceNewLineAfter Description }} +### -PlaceOpenBraceIgnoreOneLineBlock +For PSPlaceOpenBrace: ignore single-line blocks. ```yaml Type: SwitchParameter @@ -218,13 +225,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -PlaceOpenBraceOnSameLine -{{ Fill PlaceOpenBraceOnSameLine Description }} +### -PlaceCloseBraceEnable +Enable PSPlaceCloseBrace rule and configure its behavior. ```yaml Type: SwitchParameter @@ -233,13 +240,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -RemoveAllEmptyLines -{{ Fill RemoveAllEmptyLines Description }} +### -PlaceCloseBraceNewLineAfter +For PSPlaceCloseBrace: enforce a new line after the closing brace. ```yaml Type: SwitchParameter @@ -248,13 +255,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -RemoveComments -{{ Fill RemoveComments Description }} +### -PlaceCloseBraceIgnoreOneLineBlock +For PSPlaceCloseBrace: ignore single-line blocks. ```yaml Type: SwitchParameter @@ -263,13 +270,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -RemoveCommentsBeforeParamBlock -{{ Fill RemoveCommentsBeforeParamBlock Description }} +### -PlaceCloseBraceNoEmptyLineBefore +For PSPlaceCloseBrace: do not allow an empty line before a closing brace. ```yaml Type: SwitchParameter @@ -278,13 +285,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -RemoveCommentsInParamBlock -{{ Fill RemoveCommentsInParamBlock Description }} +### -UseConsistentIndentationEnable +Enable PSUseConsistentIndentation rule and configure its behavior. ```yaml Type: SwitchParameter @@ -293,106 +300,103 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -RemoveEmptyLines -{{ Fill RemoveEmptyLines Description }} +### -UseConsistentIndentationKind +Indentation style: 'space' or 'tab'. ```yaml -Type: SwitchParameter +Type: String Parameter Sets: (All) Aliases: Required: False -Position: Named +Position: 3 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -Sort -{{ Fill Sort Description }} +### -UseConsistentIndentationPipelineIndentation +Pipeline indentation mode: IncreaseIndentationAfterEveryPipeline or NoIndentation. ```yaml Type: String Parameter Sets: (All) Aliases: -Accepted values: None, Asc, Desc Required: False -Position: 1 +Position: 4 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentIndentationEnable -{{ Fill UseConsistentIndentationEnable Description }} +### -UseConsistentIndentationIndentationSize +Number of spaces for indentation when Kind is 'space'. ```yaml -Type: SwitchParameter +Type: Int32 Parameter Sets: (All) Aliases: Required: False -Position: Named -Default value: None +Position: 5 +Default value: 0 Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentIndentationIndentationSize -{{ Fill UseConsistentIndentationIndentationSize Description }} +### -UseConsistentWhitespaceEnable +Enable PSUseConsistentWhitespace rule and configure which elements to check. ```yaml -Type: Int32 +Type: SwitchParameter Parameter Sets: (All) Aliases: Required: False -Position: 4 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentIndentationKind -{{ Fill UseConsistentIndentationKind Description }} +### -UseConsistentWhitespaceCheckInnerBrace +For PSUseConsistentWhitespace: check inner brace spacing. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: -Accepted values: space, tab Required: False -Position: 2 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentIndentationPipelineIndentation -{{ Fill UseConsistentIndentationPipelineIndentation Description }} +### -UseConsistentWhitespaceCheckOpenBrace +For PSUseConsistentWhitespace: check open brace spacing. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: -Accepted values: IncreaseIndentationAfterEveryPipeline, NoIndentation Required: False -Position: 3 -Default value: None +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckInnerBrace -{{ Fill UseConsistentWhitespaceCheckInnerBrace Description }} +### -UseConsistentWhitespaceCheckOpenParen +For PSUseConsistentWhitespace: check open parenthesis spacing. ```yaml Type: SwitchParameter @@ -401,13 +405,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckOpenBrace -{{ Fill UseConsistentWhitespaceCheckOpenBrace Description }} +### -UseConsistentWhitespaceCheckOperator +For PSUseConsistentWhitespace: check operator spacing. ```yaml Type: SwitchParameter @@ -416,13 +420,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckOpenParen -{{ Fill UseConsistentWhitespaceCheckOpenParen Description }} +### -UseConsistentWhitespaceCheckPipe +For PSUseConsistentWhitespace: check pipeline operator spacing. ```yaml Type: SwitchParameter @@ -431,13 +435,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckOperator -{{ Fill UseConsistentWhitespaceCheckOperator Description }} +### -UseConsistentWhitespaceCheckSeparator +For PSUseConsistentWhitespace: check separator (comma) spacing. ```yaml Type: SwitchParameter @@ -446,13 +450,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckPipe -{{ Fill UseConsistentWhitespaceCheckPipe Description }} +### -AlignAssignmentStatementEnable +Enable PSAlignAssignmentStatement rule and optionally check hashtable alignment. ```yaml Type: SwitchParameter @@ -461,13 +465,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceCheckSeparator -{{ Fill UseConsistentWhitespaceCheckSeparator Description }} +### -AlignAssignmentStatementCheckHashtable +For PSAlignAssignmentStatement: align hashtable assignments. ```yaml Type: SwitchParameter @@ -476,13 +480,13 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseConsistentWhitespaceEnable -{{ Fill UseConsistentWhitespaceEnable Description }} +### -UseCorrectCasingEnable +Enable PSUseCorrectCasing rule. ```yaml Type: SwitchParameter @@ -491,21 +495,22 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -UseCorrectCasingEnable -{{ Fill UseCorrectCasingEnable Description }} +### -PSD1Style +Style for generated manifests (PSD1) for the selected ApplyTo targets. +'Minimal' or 'Native'. ```yaml -Type: SwitchParameter +Type: String Parameter Sets: (All) Aliases: Required: False -Position: Named +Position: 6 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -531,11 +536,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/New-ConfigurationImportModule.md b/Module/Docs/New-ConfigurationImportModule.md similarity index 100% rename from Docs/New-ConfigurationImportModule.md rename to Module/Docs/New-ConfigurationImportModule.md diff --git a/Docs/New-ConfigurationInformation.md b/Module/Docs/New-ConfigurationInformation.md similarity index 73% rename from Docs/New-ConfigurationInformation.md rename to Module/Docs/New-ConfigurationInformation.md index 4d27b9b8..68986dc4 100644 --- a/Docs/New-ConfigurationInformation.md +++ b/Module/Docs/New-ConfigurationInformation.md @@ -8,7 +8,7 @@ schema: 2.0.0 # New-ConfigurationInformation ## SYNOPSIS -{{ Fill in the Synopsis }} +Describes what to include/exclude in the module build and how libraries are organized. ## SYNTAX @@ -21,21 +21,20 @@ New-ConfigurationInformation [[-FunctionsToExportFolder] ] [[-AliasesToE ``` ## DESCRIPTION -{{ Fill in the Description }} +Emits a configuration block with folder-level include/exclude rules and optional library +locations that the builder uses to stage content prior to merge/packaging. ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +New-ConfigurationInformation -IncludeAll 'Internals\' -IncludePS1 'Private','Public' -ExcludeFromPackage 'Ignore','Docs' ``` - -{{ Add example description here }} ## PARAMETERS -### -AliasesToExportFolder -{{ Fill AliasesToExportFolder Description }} +### -FunctionsToExportFolder +Folder name containing public functions to export (e.g., 'Public'). ```yaml Type: String @@ -49,11 +48,11 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -ExcludeFromPackage -{{ Fill ExcludeFromPackage Description }} +### -AliasesToExportFolder +Folder name containing public aliases to export (e.g., 'Public'). ```yaml -Type: String[] +Type: String Parameter Sets: (All) Aliases: @@ -64,23 +63,23 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -FunctionsToExportFolder -{{ Fill FunctionsToExportFolder Description }} +### -ExcludeFromPackage +Paths or patterns to exclude from artefacts (e.g., 'Ignore','Docs','Examples'). ```yaml -Type: String +Type: String[] Parameter Sets: (All) Aliases: Required: False -Position: 0 +Position: 3 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -IncludeAll -{{ Fill IncludeAll Description }} +### -IncludeRoot +File patterns from the root to include (e.g., '*.psm1','*.psd1','License*'). ```yaml Type: String[] @@ -88,29 +87,29 @@ Parameter Sets: (All) Aliases: Required: False -Position: 5 +Position: 4 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -IncludeCustomCode -{{ Fill IncludeCustomCode Description }} +### -IncludePS1 +Folder names where PS1 files should be included (e.g., 'Private','Public','Enums','Classes'). ```yaml -Type: ScriptBlock +Type: String[] Parameter Sets: (All) Aliases: Required: False -Position: 6 +Position: 5 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -IncludePS1 -{{ Fill IncludePS1 Description }} +### -IncludeAll +Folder names to include entirely (e.g., 'Images','Resources','Templates','Bin','Lib','Data'). ```yaml Type: String[] @@ -118,29 +117,29 @@ Parameter Sets: (All) Aliases: Required: False -Position: 4 +Position: 6 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -IncludeRoot -{{ Fill IncludeRoot Description }} +### -IncludeCustomCode +Scriptblock executed during staging to add custom files/folders. ```yaml -Type: String[] +Type: ScriptBlock Parameter Sets: (All) Aliases: Required: False -Position: 3 +Position: 7 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -IncludeToArray -{{ Fill IncludeToArray Description }} +Advanced form to pass IncludeRoot/IncludePS1/IncludeAll as a single hashtable. ```yaml Type: IDictionary @@ -148,14 +147,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 7 +Position: 8 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -LibrariesCore -{{ Fill LibrariesCore Description }} +Relative path to libraries compiled for Core (default 'Lib/Core'). ```yaml Type: String @@ -163,14 +162,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 8 +Position: 9 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -LibrariesDefault -{{ Fill LibrariesDefault Description }} +Relative path to libraries for classic .NET (default 'Lib/Default'). ```yaml Type: String @@ -178,14 +177,14 @@ Parameter Sets: (All) Aliases: Required: False -Position: 9 +Position: 10 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` ### -LibrariesStandard -{{ Fill LibrariesStandard Description }} +Relative path to libraries for .NET Standard (default 'Lib/Standard'). ```yaml Type: String @@ -193,7 +192,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 10 +Position: 11 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -219,11 +218,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/New-ConfigurationManifest.md b/Module/Docs/New-ConfigurationManifest.md similarity index 90% rename from Docs/New-ConfigurationManifest.md rename to Module/Docs/New-ConfigurationManifest.md index 4779f8e2..5653fa08 100644 --- a/Docs/New-ConfigurationManifest.md +++ b/Module/Docs/New-ConfigurationManifest.md @@ -16,9 +16,10 @@ Creates a new configuration manifest for a PowerShell module. New-ConfigurationManifest [-ModuleVersion] [[-CompatiblePSEditions] ] [-GUID] [-Author] [[-CompanyName] ] [[-Copyright] ] [[-Description] ] [[-PowerShellVersion] ] [[-Tags] ] [[-IconUri] ] [[-ProjectUri] ] - [[-DotNetFrameworkVersion] ] [[-LicenseUri] ] [[-Prerelease] ] - [[-FunctionsToExport] ] [[-CmdletsToExport] ] [[-AliasesToExport] ] - [[-FormatsToProcess] ] [-ProgressAction ] [] + [[-DotNetFrameworkVersion] ] [[-LicenseUri] ] [-RequireLicenseAcceptance] + [[-Prerelease] ] [[-FunctionsToExport] ] [[-CmdletsToExport] ] + [[-AliasesToExport] ] [[-FormatsToProcess] ] [-ProgressAction ] + [] ``` ## DESCRIPTION @@ -234,6 +235,23 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -RequireLicenseAcceptance +When set, indicates the module requires explicit user license acceptance (PowerShellGet). +If enabled, ensure a license file exists at the module root; the builder will +normalize any LICENSE/License.md to 'license.txt' in the final package. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Prerelease Specifies the prerelease tag for the module. diff --git a/Docs/New-ConfigurationModule.md b/Module/Docs/New-ConfigurationModule.md similarity index 100% rename from Docs/New-ConfigurationModule.md rename to Module/Docs/New-ConfigurationModule.md diff --git a/Docs/New-ConfigurationModuleSkip.md b/Module/Docs/New-ConfigurationModuleSkip.md similarity index 100% rename from Docs/New-ConfigurationModuleSkip.md rename to Module/Docs/New-ConfigurationModuleSkip.md diff --git a/Docs/New-ConfigurationPlaceHolder.md b/Module/Docs/New-ConfigurationPlaceHolder.md similarity index 100% rename from Docs/New-ConfigurationPlaceHolder.md rename to Module/Docs/New-ConfigurationPlaceHolder.md diff --git a/Docs/New-ConfigurationPublish.md b/Module/Docs/New-ConfigurationPublish.md similarity index 100% rename from Docs/New-ConfigurationPublish.md rename to Module/Docs/New-ConfigurationPublish.md diff --git a/Docs/New-ConfigurationTest.md b/Module/Docs/New-ConfigurationTest.md similarity index 72% rename from Docs/New-ConfigurationTest.md rename to Module/Docs/New-ConfigurationTest.md index d733afc5..91003bc3 100644 --- a/Docs/New-ConfigurationTest.md +++ b/Module/Docs/New-ConfigurationTest.md @@ -8,7 +8,7 @@ schema: 2.0.0 # New-ConfigurationTest ## SYNOPSIS -{{ Fill in the Synopsis }} +Configures running Pester tests as part of the build. ## SYNTAX @@ -18,36 +18,38 @@ New-ConfigurationTest [-TestsPath] [-Enable] [-Force] [-ProgressAction ``` ## DESCRIPTION -{{ Fill in the Description }} +Emits test configuration that the builder uses to run tests. +Currently, tests +are triggered AfterMerge. +When -Enable is not provided, nothing is emitted. ## EXAMPLES -### Example 1 -```powershell -PS C:\> {{ Add example code here }} +### EXAMPLE 1 +``` +New-ConfigurationTest -Enable -TestsPath 'Tests' -Force +Configures tests to run after merge from the 'Tests' folder. ``` - -{{ Add example description here }} ## PARAMETERS -### -Enable -{{ Fill Enable Description }} +### -TestsPath +Path to the folder containing Pester tests. ```yaml -Type: SwitchParameter +Type: String Parameter Sets: (All) Aliases: -Required: False -Position: Named +Required: True +Position: 1 Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -Force -{{ Fill Force Description }} +### -Enable +Enable test execution in the build. ```yaml Type: SwitchParameter @@ -56,22 +58,22 @@ Aliases: Required: False Position: Named -Default value: None +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` -### -TestsPath -{{ Fill TestsPath Description }} +### -Force +Force running tests even if they already ran or when caching would skip them. ```yaml -Type: String +Type: SwitchParameter Parameter Sets: (All) Aliases: -Required: True -Position: 0 -Default value: None +Required: False +Position: Named +Default value: False Accept pipeline input: False Accept wildcard characters: False ``` @@ -96,11 +98,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/Publish-GitHubReleaseAsset.md b/Module/Docs/Publish-GitHubReleaseAsset.md similarity index 100% rename from Docs/Publish-GitHubReleaseAsset.md rename to Module/Docs/Publish-GitHubReleaseAsset.md diff --git a/Docs/Publish-NugetPackage.md b/Module/Docs/Publish-NugetPackage.md similarity index 100% rename from Docs/Publish-NugetPackage.md rename to Module/Docs/Publish-NugetPackage.md diff --git a/Docs/Readme.md b/Module/Docs/Readme.md similarity index 93% rename from Docs/Readme.md rename to Module/Docs/Readme.md index ea2b57a4..96f92097 100644 --- a/Docs/Readme.md +++ b/Module/Docs/Readme.md @@ -56,6 +56,9 @@ Locale: en-US ### [Initialize-ProjectManager](Initialize-ProjectManager.md) {{ Fill in the Description }} +### [Install-ProjectDocumentation](Install-ProjectDocumentation.md) +{{ Fill in the Description }} + ### [Invoke-DotNetReleaseBuild](Invoke-DotNetReleaseBuild.md) {{ Fill in the Description }} @@ -77,6 +80,9 @@ Locale: en-US ### [New-ConfigurationCompatibility](New-ConfigurationCompatibility.md) {{ Fill in the Description }} +### [New-ConfigurationDelivery](New-ConfigurationDelivery.md) +{{ Fill in the Description }} + ### [New-ConfigurationDocumentation](New-ConfigurationDocumentation.md) {{ Fill in the Description }} @@ -134,3 +140,6 @@ Locale: en-US ### [Set-ProjectVersion](Set-ProjectVersion.md) {{ Fill in the Description }} +### [Show-ProjectDocumentation](Show-ProjectDocumentation.md) +{{ Fill in the Description }} + diff --git a/Docs/Register-Certificate.md b/Module/Docs/Register-Certificate.md similarity index 63% rename from Docs/Register-Certificate.md rename to Module/Docs/Register-Certificate.md index 225f1d2d..270b8e4d 100644 --- a/Docs/Register-Certificate.md +++ b/Module/Docs/Register-Certificate.md @@ -8,26 +8,28 @@ schema: 2.0.0 # Register-Certificate ## SYNOPSIS -{{ Fill in the Synopsis }} +Signs files in a path using a code-signing certificate (Windows and PowerShell Core supported). ## SYNTAX ### PFX ``` Register-Certificate -CertificatePFX -Path [-TimeStampServer ] - [-IncludeChain ] [-Include ] [-HashAlgorithm ] [-ProgressAction ] - [-WhatIf] [-Confirm] [] + [-IncludeChain ] [-Include ] [-ExcludePath ] [-HashAlgorithm ] + [-ProgressAction ] [-WhatIf] [-Confirm] [] ``` ### Store ``` Register-Certificate -LocalStore [-Thumbprint ] -Path [-TimeStampServer ] - [-IncludeChain ] [-Include ] [-HashAlgorithm ] [-ProgressAction ] - [-WhatIf] [-Confirm] [] + [-IncludeChain ] [-Include ] [-ExcludePath ] [-HashAlgorithm ] + [-ProgressAction ] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION -{{ Fill in the Description }} +Locates a code-signing certificate (by thumbprint from the Windows cert store or from a PFX) +and applies Authenticode signatures to matching files under -Path. +On Windows, uses Set-AuthenticodeSignature; on non-Windows, uses OpenAuthenticode module if available. ## EXAMPLES @@ -41,7 +43,8 @@ PS C:\> {{ Add example code here }} ## PARAMETERS ### -CertificatePFX -{{ Fill CertificatePFX Description }} +A PFX file to use for signing. +Mutually exclusive with -LocalStore/-Thumbprint. ```yaml Type: String @@ -55,29 +58,28 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -Confirm -Prompts you for confirmation before running the cmdlet. +### -LocalStore +Certificate store to search ('LocalMachine' or 'CurrentUser') when using a certificate from the store. ```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: cf +Type: String +Parameter Sets: Store +Aliases: -Required: False +Required: True Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -HashAlgorithm -{{ Fill HashAlgorithm Description }} +### -Thumbprint +Certificate thumbprint to select a single certificate from the chosen -LocalStore. ```yaml Type: String -Parameter Sets: (All) -Aliases: -Accepted values: SHA1, SHA256, SHA384, SHA512 +Parameter Sets: Store +Aliases: CertificateThumbprint Required: False Position: Named @@ -86,75 +88,78 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -Include -{{ Fill Include Description }} +### -Path +Root directory containing files to sign. ```yaml -Type: String[] +Type: String Parameter Sets: (All) Aliases: -Required: False +Required: True Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False ``` -### -IncludeChain -{{ Fill IncludeChain Description }} +### -TimeStampServer +RFC3161 timestamp server URL. +Default: http://timestamp.digicert.com ```yaml Type: String Parameter Sets: (All) Aliases: -Accepted values: All, NotRoot, Signer Required: False Position: Named -Default value: None +Default value: Http://timestamp.digicert.com Accept pipeline input: False Accept wildcard characters: False ``` -### -LocalStore -{{ Fill LocalStore Description }} +### -IncludeChain +Which portion of the chain to include in the signature: All, NotRoot, or Signer. +Default: All. ```yaml Type: String -Parameter Sets: Store +Parameter Sets: (All) Aliases: -Accepted values: LocalMachine, CurrentUser -Required: True +Required: False Position: Named -Default value: None +Default value: All Accept pipeline input: False Accept wildcard characters: False ``` -### -Path -{{ Fill Path Description }} +### -Include +File patterns to include during signing. +Defaults to scripts only: '*.ps1','*.psd1','*.psm1'. +You may pass additional patterns if needed (e.g., '*.dll'). ```yaml -Type: String +Type: String[] Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named -Default value: None +Default value: @('*.ps1', '*.psd1', '*.psm1') Accept pipeline input: False Accept wildcard characters: False ``` -### -Thumbprint -{{ Fill Thumbprint Description }} +### -ExcludePath +One or more path substrings to exclude from signing. +Useful for skipping folders like 'Internals' unless opted-in. ```yaml -Type: String -Parameter Sets: Store -Aliases: CertificateThumbprint +Type: String[] +Parameter Sets: (All) +Aliases: Required: False Position: Named @@ -163,8 +168,9 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -TimeStampServer -{{ Fill TimeStampServer Description }} +### -HashAlgorithm +Hash algorithm for the signature. +Default: SHA256. ```yaml Type: String @@ -173,7 +179,7 @@ Aliases: Required: False Position: Named -Default value: None +Default value: SHA256 Accept pipeline input: False Accept wildcard characters: False ``` @@ -194,6 +200,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ProgressAction {{ Fill ProgressAction Description }} @@ -214,11 +235,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## INPUTS -### None - ## OUTPUTS -### System.Object ## NOTES ## RELATED LINKS diff --git a/Docs/Remove-Comments.md b/Module/Docs/Remove-Comments.md similarity index 100% rename from Docs/Remove-Comments.md rename to Module/Docs/Remove-Comments.md diff --git a/Docs/Remove-ProjectFiles.md b/Module/Docs/Remove-ProjectFiles.md similarity index 100% rename from Docs/Remove-ProjectFiles.md rename to Module/Docs/Remove-ProjectFiles.md diff --git a/Docs/Send-GitHubRelease.md b/Module/Docs/Send-GitHubRelease.md similarity index 100% rename from Docs/Send-GitHubRelease.md rename to Module/Docs/Send-GitHubRelease.md diff --git a/Docs/Set-ProjectVersion.md b/Module/Docs/Set-ProjectVersion.md similarity index 100% rename from Docs/Set-ProjectVersion.md rename to Module/Docs/Set-ProjectVersion.md diff --git a/Module/Docs/Show-ProjectDocumentation.md b/Module/Docs/Show-ProjectDocumentation.md new file mode 100644 index 00000000..7c6d6325 --- /dev/null +++ b/Module/Docs/Show-ProjectDocumentation.md @@ -0,0 +1,388 @@ +--- +external help file: PSPublishModule-help.xml +Module Name: PSPublishModule +online version: +schema: 2.0.0 +--- + +# Show-ProjectDocumentation + +## SYNOPSIS +Shows README/CHANGELOG or a chosen document for a module, with a simple console view. + +## SYNTAX + +### ByName (Default) +``` +Show-ProjectDocumentation [[-Name] ] [-RequiredVersion ] [-Readme] [-Changelog] [-License] + [-Intro] [-Upgrade] [-All] [-Links] [-File ] [-PreferInternals] [-List] [-Raw] [-Open] + [-ProgressAction ] [] +``` + +### ByModule +``` +Show-ProjectDocumentation [-Module ] [-RequiredVersion ] [-Readme] [-Changelog] + [-License] [-Intro] [-Upgrade] [-All] [-Links] [-File ] [-PreferInternals] [-List] [-Raw] [-Open] + [-ProgressAction ] [] +``` + +### ByPath +``` +Show-ProjectDocumentation [-RequiredVersion ] [-DocsPath ] [-Readme] [-Changelog] [-License] + [-Intro] [-Upgrade] [-All] [-Links] [-File ] [-PreferInternals] [-List] [-Raw] [-Open] + [-ProgressAction ] [] +``` + +## DESCRIPTION +Finds a module (by name or PSModuleInfo) and renders README/CHANGELOG from the module root +or from its Internals folder (as defined in PrivateData.PSData.Delivery). +You can also point directly to a docs folder via -DocsPath (e.g., output of Install-ModuleDocumentation). + +## EXAMPLES + +### EXAMPLE 1 +``` +Show-ProjectDocumentation -Name EFAdminManager -Readme +``` + +### EXAMPLE 2 +``` +Get-Module -ListAvailable EFAdminManager | Show-ProjectDocumentation -Changelog +``` + +### EXAMPLE 3 +``` +Show-ProjectDocumentation -DocsPath 'C:\Docs\EFAdminManager\3.0.0' -Readme -Open +``` + +### EXAMPLE 4 +``` +Show-ProjectDocumentation -Name EFAdminManager -License +``` + +### EXAMPLE 5 +``` +Show-ProjectDocumentation -Name EFAdminManager -Intro +``` + +### EXAMPLE 6 +``` +Show-ProjectDocumentation -Name EFAdminManager -Upgrade +``` + +### EXAMPLE 7 +``` +Show-ProjectDocumentation -Name EFAdminManager -List +``` + +### EXAMPLE 8 +``` +Show-ProjectDocumentation -Name EFAdminManager -All -Links +Displays Introduction, README, CHANGELOG, LICENSE and prints ImportantLinks. +``` + +### EXAMPLE 9 +``` +# Prefer Internals copy of README/CHANGELOG when both root and Internals exist +Show-ProjectDocumentation -Name EFAdminManager -Readme -Changelog -PreferInternals +``` + +### EXAMPLE 10 +``` +# Show a specific file from a copied docs folder +Show-ProjectDocumentation -DocsPath 'C:\\Docs\\EFAdminManager\\3.0.0' -File 'Internals\\Docs\\HowTo.md' +``` + +### EXAMPLE 11 +``` +# Quick list of found README/CHANGELOG/License in root and Internals +Show-ProjectDocumentation -Name EFAdminManager -List | Format-Table -Auto +``` + +### EXAMPLE 12 +``` +# Open the resolved README in the default viewer +Show-ProjectDocumentation -Name EFAdminManager -Readme -Open +``` + +## PARAMETERS + +### -Name +Module name to show documentation for. +Accepts pipeline by value. + +```yaml +Type: String +Parameter Sets: ByName +Aliases: ModuleName + +Required: False +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -Module +A PSModuleInfo object (e.g., from Get-Module -ListAvailable) to operate on directly. + +```yaml +Type: PSModuleInfo +Parameter Sets: ByModule +Aliases: InputObject, ModuleInfo + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -RequiredVersion +Specific version of the module to target. +If omitted, selects the highest available. + +```yaml +Type: Version +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DocsPath +A folder that contains documentation to display (e.g., the destination created by Install-ModuleDocumentation). +When provided, the cmdlet does not look up the module and shows docs from this folder. + +```yaml +Type: String +Parameter Sets: ByPath +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Readme +Show README*. +If both root and Internals copies exist, the root copy is preferred unless -PreferInternals is set. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Changelog +Show CHANGELOG*. +If both root and Internals copies exist, the root copy is preferred unless -PreferInternals is set. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -License +Show LICENSE. +If multiple variants exist (LICENSE.md, LICENSE.txt), the resolver prefers a normalized 'license.txt' in +the chosen area (root vs Internals). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Intro +Show introduction text defined in PrivateData.PSData.Delivery.IntroText when available. +If not defined, +falls back to README resolution (root vs Internals honoring -PreferInternals). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Upgrade +Show upgrade text defined in PrivateData.PSData.Delivery.UpgradeText when available. +If not defined, +looks for an UPGRADE* file; otherwise throws. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -All +Show Introduction, README, CHANGELOG and LICENSE in a standard order. +You can still add +specific switches (e.g., -Changelog) and they will be included additively without duplication. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Links +Print ImportantLinks defined in PrivateData.PSData.Delivery after the selected documents. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -File +Relative path to a specific file to display (relative to module root or Internals). +If rooted, used as-is. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PreferInternals +Prefer the Internals copy of README/CHANGELOG when both exist. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -List +List available README/CHANGELOG files found (root and Internals) instead of displaying content. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Raw +Output the raw file content (no styling). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Open +Open the resolved file in the system default viewer instead of rendering in the console. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/Documentation/INTEGRATION_SUMMARY.md b/Module/Documentation/INTEGRATION_SUMMARY.md similarity index 100% rename from Documentation/INTEGRATION_SUMMARY.md rename to Module/Documentation/INTEGRATION_SUMMARY.md diff --git a/Documentation/REFACTORING_SUMMARY.md b/Module/Documentation/REFACTORING_SUMMARY.md similarity index 100% rename from Documentation/REFACTORING_SUMMARY.md rename to Module/Documentation/REFACTORING_SUMMARY.md diff --git a/Documentation/Templates/AGENTS.MD b/Module/Documentation/Templates/AGENTS.MD similarity index 100% rename from Documentation/Templates/AGENTS.MD rename to Module/Documentation/Templates/AGENTS.MD diff --git a/Documentation/Templates/TASKS-DOCUMENTATION.MD b/Module/Documentation/Templates/TASKS-DOCUMENTATION.MD similarity index 100% rename from Documentation/Templates/TASKS-DOCUMENTATION.MD rename to Module/Documentation/Templates/TASKS-DOCUMENTATION.MD diff --git a/Examples/CSharpFunctionality/Example.BuildAndPublishNugets.ps1 b/Module/Examples/CSharpFunctionality/Example.BuildAndPublishNugets.ps1 similarity index 100% rename from Examples/CSharpFunctionality/Example.BuildAndPublishNugets.ps1 rename to Module/Examples/CSharpFunctionality/Example.BuildAndPublishNugets.ps1 diff --git a/Examples/Example.CmdletAliasDetection.ps1 b/Module/Examples/Example.CmdletAliasDetection.ps1 similarity index 100% rename from Examples/Example.CmdletAliasDetection.ps1 rename to Module/Examples/Example.CmdletAliasDetection.ps1 diff --git a/Examples/Example.CompleteNuGetSigning.ps1 b/Module/Examples/Example.CompleteNuGetSigning.ps1 similarity index 100% rename from Examples/Example.CompleteNuGetSigning.ps1 rename to Module/Examples/Example.CompleteNuGetSigning.ps1 diff --git a/Examples/Example.DetectUsedLibraries.ps1 b/Module/Examples/Example.DetectUsedLibraries.ps1 similarity index 100% rename from Examples/Example.DetectUsedLibraries.ps1 rename to Module/Examples/Example.DetectUsedLibraries.ps1 diff --git a/Examples/Example.FindMicrosoftClientIdentity.ps1 b/Module/Examples/Example.FindMicrosoftClientIdentity.ps1 similarity index 100% rename from Examples/Example.FindMicrosoftClientIdentity.ps1 rename to Module/Examples/Example.FindMicrosoftClientIdentity.ps1 diff --git a/Examples/Example.RegisterCertificate.ps1 b/Module/Examples/Example.RegisterCertificate.ps1 similarity index 100% rename from Examples/Example.RegisterCertificate.ps1 rename to Module/Examples/Example.RegisterCertificate.ps1 diff --git a/Examples/Example.RemoveComments.ps1.ps1 b/Module/Examples/Example.RemoveComments.ps1.ps1 similarity index 100% rename from Examples/Example.RemoveComments.ps1.ps1 rename to Module/Examples/Example.RemoveComments.ps1.ps1 diff --git a/Examples/Example.RemoveProjectFiles.ps1 b/Module/Examples/Example.RemoveProjectFiles.ps1 similarity index 100% rename from Examples/Example.RemoveProjectFiles.ps1 rename to Module/Examples/Example.RemoveProjectFiles.ps1 diff --git a/Examples/Example.SignMultipleFiles.ps1 b/Module/Examples/Example.SignMultipleFiles.ps1 similarity index 100% rename from Examples/Example.SignMultipleFiles.ps1 rename to Module/Examples/Example.SignMultipleFiles.ps1 diff --git a/Examples/Step01.CreateModuleProject.ps1 b/Module/Examples/Step01.CreateModuleProject.ps1 similarity index 100% rename from Examples/Step01.CreateModuleProject.ps1 rename to Module/Examples/Step01.CreateModuleProject.ps1 diff --git a/Examples/Step02.BuildModuleOver.ps1 b/Module/Examples/Step02.BuildModuleOver.ps1 similarity index 100% rename from Examples/Step02.BuildModuleOver.ps1 rename to Module/Examples/Step02.BuildModuleOver.ps1 diff --git a/Examples/Step03.PrepareVariablesForGitHubActions.ps1 b/Module/Examples/Step03.PrepareVariablesForGitHubActions.ps1 similarity index 100% rename from Examples/Step03.PrepareVariablesForGitHubActions.ps1 rename to Module/Examples/Step03.PrepareVariablesForGitHubActions.ps1 diff --git a/Examples/SupportFunctionality/Example.PowerShellCompatibility.ps1 b/Module/Examples/SupportFunctionality/Example.PowerShellCompatibility.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.PowerShellCompatibility.ps1 rename to Module/Examples/SupportFunctionality/Example.PowerShellCompatibility.ps1 diff --git a/Examples/SupportFunctionality/Example.ProjectEncodingNewLines.ps1 b/Module/Examples/SupportFunctionality/Example.ProjectEncodingNewLines.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.ProjectEncodingNewLines.ps1 rename to Module/Examples/SupportFunctionality/Example.ProjectEncodingNewLines.ps1 diff --git a/Examples/SupportFunctionality/Example.TestEncoding.ps1 b/Module/Examples/SupportFunctionality/Example.TestEncoding.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.TestEncoding.ps1 rename to Module/Examples/SupportFunctionality/Example.TestEncoding.ps1 diff --git a/Examples/SupportFunctionality/Example.TestEncodingConversion.ps1 b/Module/Examples/SupportFunctionality/Example.TestEncodingConversion.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.TestEncodingConversion.ps1 rename to Module/Examples/SupportFunctionality/Example.TestEncodingConversion.ps1 diff --git a/Examples/SupportFunctionality/Example.TestLineEnding.ps1 b/Module/Examples/SupportFunctionality/Example.TestLineEnding.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.TestLineEnding.ps1 rename to Module/Examples/SupportFunctionality/Example.TestLineEnding.ps1 diff --git a/Examples/SupportFunctionality/Example.TestLineEndingConversion.ps1 b/Module/Examples/SupportFunctionality/Example.TestLineEndingConversion.ps1 similarity index 100% rename from Examples/SupportFunctionality/Example.TestLineEndingConversion.ps1 rename to Module/Examples/SupportFunctionality/Example.TestLineEndingConversion.ps1 diff --git a/Examples/TestingFunctionality/Example.ModuleTestingAdvanced.ps1 b/Module/Examples/TestingFunctionality/Example.ModuleTestingAdvanced.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.ModuleTestingAdvanced.ps1 rename to Module/Examples/TestingFunctionality/Example.ModuleTestingAdvanced.ps1 diff --git a/Examples/TestingFunctionality/Example.ModuleTestingBasic.ps1 b/Module/Examples/TestingFunctionality/Example.ModuleTestingBasic.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.ModuleTestingBasic.ps1 rename to Module/Examples/TestingFunctionality/Example.ModuleTestingBasic.ps1 diff --git a/Examples/TestingFunctionality/Example.ModuleTestingCICD.ps1 b/Module/Examples/TestingFunctionality/Example.ModuleTestingCICD.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.ModuleTestingCICD.ps1 rename to Module/Examples/TestingFunctionality/Example.ModuleTestingCICD.ps1 diff --git a/Examples/TestingFunctionality/Example.ModuleTestingCICDAdvanced.ps1 b/Module/Examples/TestingFunctionality/Example.ModuleTestingCICDAdvanced.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.ModuleTestingCICDAdvanced.ps1 rename to Module/Examples/TestingFunctionality/Example.ModuleTestingCICDAdvanced.ps1 diff --git a/Examples/TestingFunctionality/Example.ModuleTestingIndividualFunctions.ps1 b/Module/Examples/TestingFunctionality/Example.ModuleTestingIndividualFunctions.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.ModuleTestingIndividualFunctions.ps1 rename to Module/Examples/TestingFunctionality/Example.ModuleTestingIndividualFunctions.ps1 diff --git a/Examples/TestingFunctionality/Example.TestFailureAnalysis.ps1 b/Module/Examples/TestingFunctionality/Example.TestFailureAnalysis.ps1 similarity index 100% rename from Examples/TestingFunctionality/Example.TestFailureAnalysis.ps1 rename to Module/Examples/TestingFunctionality/Example.TestFailureAnalysis.ps1 diff --git a/Examples/TestingFunctionality/README.md b/Module/Examples/TestingFunctionality/README.md similarity index 100% rename from Examples/TestingFunctionality/README.md rename to Module/Examples/TestingFunctionality/README.md diff --git a/PSPublishModule.Tests.ps1 b/Module/PSPublishModule.Tests.ps1 similarity index 100% rename from PSPublishModule.Tests.ps1 rename to Module/PSPublishModule.Tests.ps1 diff --git a/PSPublishModule.psd1 b/Module/PSPublishModule.psd1 similarity index 66% rename from PSPublishModule.psd1 rename to Module/PSPublishModule.psd1 index 0a806ebc..d7f4128c 100644 --- a/PSPublishModule.psd1 +++ b/Module/PSPublishModule.psd1 @@ -7,15 +7,16 @@ Copyright = '(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.' Description = 'Simple project allowing preparing, managing, building and publishing modules to PowerShellGallery' DotNetFrameworkVersion = '4.5.2' - FunctionsToExport = @('Convert-ProjectEncoding', 'Convert-ProjectLineEnding', 'Export-CertificateForNuGet', 'Get-MissingFunctions', 'Get-ModuleInformation', 'Get-ModuleTestFailures', 'Get-PowerShellAssemblyMetadata', 'Get-PowerShellCompatibility', 'Get-ProjectConsistency', 'Get-ProjectEncoding', 'Get-ProjectLineEnding', 'Get-ProjectVersion', 'Initialize-PortableModule', 'Initialize-PortableScript', 'Initialize-ProjectManager', 'Invoke-DotNetReleaseBuild', 'Invoke-ModuleBuild', 'Invoke-ModuleTestSuite', 'New-ConfigurationArtefact', 'New-ConfigurationBuild', 'New-ConfigurationCommand', 'New-ConfigurationCompatibility', 'New-ConfigurationDocumentation', 'New-ConfigurationExecute', 'New-ConfigurationFileConsistency', 'New-ConfigurationFormat', 'New-ConfigurationImportModule', 'New-ConfigurationInformation', 'New-ConfigurationManifest', 'New-ConfigurationModule', 'New-ConfigurationModuleSkip', 'New-ConfigurationPlaceHolder', 'New-ConfigurationPublish', 'New-ConfigurationTest', 'Publish-GitHubReleaseAsset', 'Publish-NugetPackage', 'Register-Certificate', 'Remove-Comments', 'Remove-ProjectFiles', 'Send-GitHubRelease', 'Set-ProjectVersion') + FunctionsToExport = @('Convert-ProjectEncoding', 'Convert-ProjectLineEnding', 'Export-CertificateForNuGet', 'Get-MissingFunctions', 'Get-ModuleInformation', 'Get-ModuleTestFailures', 'Get-PowerShellAssemblyMetadata', 'Get-PowerShellCompatibility', 'Get-ProjectConsistency', 'Get-ProjectEncoding', 'Get-ProjectLineEnding', 'Get-ProjectVersion', 'Initialize-PortableModule', 'Initialize-PortableScript', 'Initialize-ProjectManager', 'Install-ProjectDocumentation', 'Invoke-DotNetReleaseBuild', 'Invoke-ModuleBuild', 'Invoke-ModuleTestSuite', 'New-ConfigurationArtefact', 'New-ConfigurationBuild', 'New-ConfigurationCommand', 'New-ConfigurationCompatibility', 'New-ConfigurationDelivery', 'New-ConfigurationDocumentation', 'New-ConfigurationExecute', 'New-ConfigurationFileConsistency', 'New-ConfigurationFormat', 'New-ConfigurationImportModule', 'New-ConfigurationInformation', 'New-ConfigurationManifest', 'New-ConfigurationModule', 'New-ConfigurationModuleSkip', 'New-ConfigurationPlaceHolder', 'New-ConfigurationPublish', 'New-ConfigurationTest', 'Publish-GitHubReleaseAsset', 'Publish-NugetPackage', 'Register-Certificate', 'Remove-Comments', 'Remove-ProjectFiles', 'Send-GitHubRelease', 'Set-ProjectVersion', 'Show-ProjectDocumentation') GUID = 'eb76426a-1992-40a5-82cd-6480f883ef4d' - ModuleVersion = '2.0.25' + ModuleVersion = '2.0.26' PowerShellVersion = '5.1' PrivateData = @{ PSData = @{ ExternalModuleDependencies = @('Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Archive', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Security') IconUri = 'https://evotec.xyz/wp-content/uploads/2019/02/PSPublishModule.png' ProjectUri = 'https://github.com/EvotecIT/PSPublishModule' + RequireLicenseAcceptance = $false Tags = @('Windows', 'MacOS', 'Linux', 'Build', 'Module') } } @@ -31,6 +32,10 @@ Guid = 'a699dea5-2c73-4616-a270-1f7abb777e71' ModuleName = 'Pester' ModuleVersion = '5.7.1' + }, @{ + Guid = 'e4e0bda1-0703-44a5-b70d-8fe704cd0643' + ModuleName = 'Microsoft.PowerShell.PSResourceGet' + ModuleVersion = '1.1.1' }, 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Archive', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Security') RootModule = 'PSPublishModule.psm1' } \ No newline at end of file diff --git a/PSPublishModule.psm1 b/Module/PSPublishModule.psm1 similarity index 100% rename from PSPublishModule.psm1 rename to Module/PSPublishModule.psm1 diff --git a/Private/Add-Artefact.ps1 b/Module/Private/Add-Artefact.ps1 similarity index 100% rename from Private/Add-Artefact.ps1 rename to Module/Private/Add-Artefact.ps1 diff --git a/Private/Add-BinaryImportModule.ps1 b/Module/Private/Add-BinaryImportModule.ps1 similarity index 100% rename from Private/Add-BinaryImportModule.ps1 rename to Module/Private/Add-BinaryImportModule.ps1 diff --git a/Private/Add-Directory.ps1 b/Module/Private/Add-Directory.ps1 similarity index 100% rename from Private/Add-Directory.ps1 rename to Module/Private/Add-Directory.ps1 diff --git a/Private/Approve-RequiredModules.ps1 b/Module/Private/Approve-RequiredModules.ps1 similarity index 100% rename from Private/Approve-RequiredModules.ps1 rename to Module/Private/Approve-RequiredModules.ps1 diff --git a/Private/Compare-ModuleVersion.ps1 b/Module/Private/Compare-ModuleVersion.ps1 similarity index 100% rename from Private/Compare-ModuleVersion.ps1 rename to Module/Private/Compare-ModuleVersion.ps1 diff --git a/Private/Compress-Artefact.ps1 b/Module/Private/Compress-Artefact.ps1 similarity index 100% rename from Private/Compress-Artefact.ps1 rename to Module/Private/Compress-Artefact.ps1 diff --git a/Private/Convert-CommandsToList.ps1 b/Module/Private/Convert-CommandsToList.ps1 similarity index 100% rename from Private/Convert-CommandsToList.ps1 rename to Module/Private/Convert-CommandsToList.ps1 diff --git a/Private/Convert-FileEncoding.ps1 b/Module/Private/Convert-FileEncoding.ps1 similarity index 100% rename from Private/Convert-FileEncoding.ps1 rename to Module/Private/Convert-FileEncoding.ps1 diff --git a/Private/Convert-FileEncodingSingle.ps1 b/Module/Private/Convert-FileEncodingSingle.ps1 similarity index 100% rename from Private/Convert-FileEncodingSingle.ps1 rename to Module/Private/Convert-FileEncodingSingle.ps1 diff --git a/Private/Convert-FolderEncoding.ps1 b/Module/Private/Convert-FolderEncoding.ps1 similarity index 100% rename from Private/Convert-FolderEncoding.ps1 rename to Module/Private/Convert-FolderEncoding.ps1 diff --git a/Private/Convert-HashTableToNicelyFormattedString.ps1 b/Module/Private/Convert-HashTableToNicelyFormattedString.ps1 similarity index 100% rename from Private/Convert-HashTableToNicelyFormattedString.ps1 rename to Module/Private/Convert-HashTableToNicelyFormattedString.ps1 diff --git a/Private/Convert-LineEnding.ps1 b/Module/Private/Convert-LineEnding.ps1 similarity index 100% rename from Private/Convert-LineEnding.ps1 rename to Module/Private/Convert-LineEnding.ps1 diff --git a/Private/Convert-RequiredModules.ps1 b/Module/Private/Convert-RequiredModules.ps1 similarity index 100% rename from Private/Convert-RequiredModules.ps1 rename to Module/Private/Convert-RequiredModules.ps1 diff --git a/Private/Copy-ArtefactMainModule.ps1 b/Module/Private/Copy-ArtefactMainModule.ps1 similarity index 100% rename from Private/Copy-ArtefactMainModule.ps1 rename to Module/Private/Copy-ArtefactMainModule.ps1 diff --git a/Private/Copy-ArtefactRequiredFiles.ps1 b/Module/Private/Copy-ArtefactRequiredFiles.ps1 similarity index 100% rename from Private/Copy-ArtefactRequiredFiles.ps1 rename to Module/Private/Copy-ArtefactRequiredFiles.ps1 diff --git a/Private/Copy-ArtefactRequiredFolders.ps1 b/Module/Private/Copy-ArtefactRequiredFolders.ps1 similarity index 100% rename from Private/Copy-ArtefactRequiredFolders.ps1 rename to Module/Private/Copy-ArtefactRequiredFolders.ps1 diff --git a/Private/Copy-ArtefactRequiredModule.ps1 b/Module/Private/Copy-ArtefactRequiredModule.ps1 similarity index 100% rename from Private/Copy-ArtefactRequiredModule.ps1 rename to Module/Private/Copy-ArtefactRequiredModule.ps1 diff --git a/Private/Copy-ArtefactToScript.ps1.ps1 b/Module/Private/Copy-ArtefactToScript.ps1.ps1 similarity index 100% rename from Private/Copy-ArtefactToScript.ps1.ps1 rename to Module/Private/Copy-ArtefactToScript.ps1.ps1 diff --git a/Private/Copy-DictionaryManual.ps1 b/Module/Private/Copy-DictionaryManual.ps1 similarity index 100% rename from Private/Copy-DictionaryManual.ps1 rename to Module/Private/Copy-DictionaryManual.ps1 diff --git a/Private/Copy-InternalDictionary.ps1 b/Module/Private/Copy-InternalDictionary.ps1 similarity index 100% rename from Private/Copy-InternalDictionary.ps1 rename to Module/Private/Copy-InternalDictionary.ps1 diff --git a/Private/Copy-InternalFiles.ps1 b/Module/Private/Copy-InternalFiles.ps1 similarity index 100% rename from Private/Copy-InternalFiles.ps1 rename to Module/Private/Copy-InternalFiles.ps1 diff --git a/Module/Private/Copy-PSPDirectoryTree.ps1 b/Module/Private/Copy-PSPDirectoryTree.ps1 new file mode 100644 index 00000000..a5d75862 --- /dev/null +++ b/Module/Private/Copy-PSPDirectoryTree.ps1 @@ -0,0 +1,27 @@ +function Copy-PSPDirectoryTree { + [CmdletBinding()] + param( + [Parameter(Mandatory)][string] $Source, + [Parameter(Mandatory)][string] $Destination, + [switch] $Overwrite + ) + if (-not (Test-Path -LiteralPath $Source)) { return } + if (-not (Test-Path -LiteralPath $Destination)) { + New-Item -ItemType Directory -Path $Destination -Force | Out-Null + } + $items = Get-ChildItem -LiteralPath $Source -Force -ErrorAction SilentlyContinue + foreach ($item in $items) { + $target = Join-Path $Destination $item.Name + if ($item.PSIsContainer) { + Copy-PSPDirectoryTree -Source $item.FullName -Destination $target -Overwrite:$Overwrite.IsPresent + } else { + try { + Copy-Item -LiteralPath $item.FullName -Destination $target -Force:$Overwrite.IsPresent -ErrorAction Stop + } catch { + if (-not (Test-Path -LiteralPath $target)) { throw } + # If not overwriting and file exists, skip silently + } + } + } +} + diff --git a/Private/Export-PSData.ps1 b/Module/Private/Export-PSData.ps1 similarity index 100% rename from Private/Export-PSData.ps1 rename to Module/Private/Export-PSData.ps1 diff --git a/Private/Find-NetFramework.ps1 b/Module/Private/Find-NetFramework.ps1 similarity index 100% rename from Private/Find-NetFramework.ps1 rename to Module/Private/Find-NetFramework.ps1 diff --git a/Private/Find-RequiredModules.ps1 b/Module/Private/Find-RequiredModules.ps1 similarity index 100% rename from Private/Find-RequiredModules.ps1 rename to Module/Private/Find-RequiredModules.ps1 diff --git a/Private/Format-Code.ps1 b/Module/Private/Format-Code.ps1 similarity index 100% rename from Private/Format-Code.ps1 rename to Module/Private/Format-Code.ps1 diff --git a/Private/Format-UsingNamespace.ps1 b/Module/Private/Format-UsingNamespace.ps1 similarity index 100% rename from Private/Format-UsingNamespace.ps1 rename to Module/Private/Format-UsingNamespace.ps1 diff --git a/Private/Get-AstTokens.ps1 b/Module/Private/Get-AstTokens.ps1 similarity index 58% rename from Private/Get-AstTokens.ps1 rename to Module/Private/Get-AstTokens.ps1 index 49d73173..2540ea3e 100644 --- a/Private/Get-AstTokens.ps1 +++ b/Module/Private/Get-AstTokens.ps1 @@ -30,11 +30,27 @@ }, $true ) + # Language keywords and control tokens that can appear in CommandAsts under some constructs + $Reserved = @( + 'if','elseif','else','switch','for','foreach','while','do','until', + 'try','catch','finally','throw','trap','break','continue','return', + 'function','filter','workflow','configuration','class','enum','data', + 'param','begin','process','end','in','using' + ) + $List = foreach ($Function in $ListOfFuncionsAst) { - $Line = $Function.CommandElements[0] - if ($Line.Value) { - $Line.Value + try { + $name = $Function.GetCommandName() + if ([string]::IsNullOrWhiteSpace($name)) { continue } + if ($name -in $Reserved) { continue } + # Exclude common redirection-like tokens that could surface as commands in edge cases + if ($name -in '>', '>>', '2>', '2>>', '|') { continue } + $name + } catch { + # Fallback to first element value when safe + $Line = $Function.CommandElements[0] + if ($Line -and $Line.Value -and ($Line.Value -notin $Reserved)) { $Line.Value } } } $List -} \ No newline at end of file +} diff --git a/Private/Get-CurrentLineEnding.ps1 b/Module/Private/Get-CurrentLineEnding.ps1 similarity index 100% rename from Private/Get-CurrentLineEnding.ps1 rename to Module/Private/Get-CurrentLineEnding.ps1 diff --git a/Private/Get-CurrentVersionFromBuildScript.ps1 b/Module/Private/Get-CurrentVersionFromBuildScript.ps1 similarity index 100% rename from Private/Get-CurrentVersionFromBuildScript.ps1 rename to Module/Private/Get-CurrentVersionFromBuildScript.ps1 diff --git a/Private/Get-CurrentVersionFromCsProj.ps1 b/Module/Private/Get-CurrentVersionFromCsProj.ps1 similarity index 100% rename from Private/Get-CurrentVersionFromCsProj.ps1 rename to Module/Private/Get-CurrentVersionFromCsProj.ps1 diff --git a/Private/Get-CurrentVersionFromPsd1.ps1 b/Module/Private/Get-CurrentVersionFromPsd1.ps1 similarity index 100% rename from Private/Get-CurrentVersionFromPsd1.ps1 rename to Module/Private/Get-CurrentVersionFromPsd1.ps1 diff --git a/Private/Get-FailuresFromPesterResults.ps1 b/Module/Private/Get-FailuresFromPesterResults.ps1 similarity index 100% rename from Private/Get-FailuresFromPesterResults.ps1 rename to Module/Private/Get-FailuresFromPesterResults.ps1 diff --git a/Private/Get-FailuresFromXmlFile.ps1 b/Module/Private/Get-FailuresFromXmlFile.ps1 similarity index 100% rename from Private/Get-FailuresFromXmlFile.ps1 rename to Module/Private/Get-FailuresFromXmlFile.ps1 diff --git a/Private/Get-FileEncoding.ps1 b/Module/Private/Get-FileEncoding.ps1 similarity index 100% rename from Private/Get-FileEncoding.ps1 rename to Module/Private/Get-FileEncoding.ps1 diff --git a/Private/Get-FilteredScriptCommands.ps1 b/Module/Private/Get-FilteredScriptCommands.ps1 similarity index 100% rename from Private/Get-FilteredScriptCommands.ps1 rename to Module/Private/Get-FilteredScriptCommands.ps1 diff --git a/Private/Get-FolderEncoding.ps1 b/Module/Private/Get-FolderEncoding.ps1 similarity index 100% rename from Private/Get-FolderEncoding.ps1 rename to Module/Private/Get-FolderEncoding.ps1 diff --git a/Private/Get-FunctionAliases.ps1 b/Module/Private/Get-FunctionAliases.ps1 similarity index 100% rename from Private/Get-FunctionAliases.ps1 rename to Module/Private/Get-FunctionAliases.ps1 diff --git a/Private/Get-FunctionAliasesFromFolder.ps1 b/Module/Private/Get-FunctionAliasesFromFolder.ps1 similarity index 100% rename from Private/Get-FunctionAliasesFromFolder.ps1 rename to Module/Private/Get-FunctionAliasesFromFolder.ps1 diff --git a/Private/Get-FunctionNames.ps1 b/Module/Private/Get-FunctionNames.ps1 similarity index 100% rename from Private/Get-FunctionNames.ps1 rename to Module/Private/Get-FunctionNames.ps1 diff --git a/Private/Get-GitLog.ps1 b/Module/Private/Get-GitLog.ps1 similarity index 100% rename from Private/Get-GitLog.ps1 rename to Module/Private/Get-GitLog.ps1 diff --git a/Private/Get-LineEndingType.ps1 b/Module/Private/Get-LineEndingType.ps1 similarity index 100% rename from Private/Get-LineEndingType.ps1 rename to Module/Private/Get-LineEndingType.ps1 diff --git a/Module/Private/Get-PSPDirectoriesPruned.ps1 b/Module/Private/Get-PSPDirectoriesPruned.ps1 new file mode 100644 index 00000000..9a3c53f8 --- /dev/null +++ b/Module/Private/Get-PSPDirectoriesPruned.ps1 @@ -0,0 +1,33 @@ +function Get-PSPDirectoriesPruned { + [CmdletBinding()] + param( + [Parameter(Mandatory)][string] $BasePath, + [Parameter(Mandatory)][string[]] $ScanRelativeDirs, + [string[]] $ExcludeNames = @(), + [string[]] $PruneNames = @('.git','obj','bin','.vs','node_modules','dist','out','Ignore'), + [switch] $FollowSymlink + ) + $list = New-Object System.Collections.Generic.List[System.IO.DirectoryInfo] + foreach ($rel in ($ScanRelativeDirs | Where-Object { $_ -and -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique)) { + $root = Join-Path $BasePath $rel + if (-not (Test-Path -LiteralPath $root)) { continue } + try { $rootDir = Get-Item -LiteralPath $root -ErrorAction Stop } catch { continue } + if (-not $rootDir.PSIsContainer) { continue } + + $stack = New-Object System.Collections.Stack + $stack.Push($rootDir) + while ($stack.Count -gt 0) { + $dir = [System.IO.DirectoryInfo]$stack.Pop() + if ($null -eq $dir) { continue } + $name = $dir.Name + if ($name -like '.*') { continue } + if ($PruneNames -contains $name) { continue } + if ($ExcludeNames -contains $name) { continue } + if (-not $FollowSymlink -and ($dir.Attributes -band [IO.FileAttributes]::ReparsePoint)) { continue } + $list.Add($dir) | Out-Null + try { $children = Get-ChildItem -LiteralPath $dir.FullName -Directory -ErrorAction Stop } catch { continue } + foreach ($child in $children) { $stack.Push($child) } + } + } + $list.ToArray() +} diff --git a/Module/Private/Get-PSPFilesPruned.ps1 b/Module/Private/Get-PSPFilesPruned.ps1 new file mode 100644 index 00000000..db740dd8 --- /dev/null +++ b/Module/Private/Get-PSPFilesPruned.ps1 @@ -0,0 +1,15 @@ +function Get-PSPFilesPruned { + [CmdletBinding()] + param( + [Parameter(Mandatory)][System.IO.DirectoryInfo[]] $Directories, + [switch] $FollowSymlink + ) + $files = New-Object System.Collections.Generic.List[System.IO.FileInfo] + foreach ($dir in $Directories) { + if (-not $FollowSymlink -and ($dir.Attributes -band [IO.FileAttributes]::ReparsePoint)) { continue } + try { $localFiles = Get-ChildItem -LiteralPath $dir.FullName -File -ErrorAction Stop } catch { $localFiles = @() } + foreach ($f in $localFiles) { $files.Add($f) | Out-Null } + } + $files.ToArray() +} + diff --git a/Private/Get-PowerShellFileCompatibility.ps1 b/Module/Private/Get-PowerShellFileCompatibility.ps1 similarity index 100% rename from Private/Get-PowerShellFileCompatibility.ps1 rename to Module/Private/Get-PowerShellFileCompatibility.ps1 diff --git a/Private/Get-ProjectCleanupPatterns.ps1 b/Module/Private/Get-ProjectCleanupPatterns.ps1 similarity index 100% rename from Private/Get-ProjectCleanupPatterns.ps1 rename to Module/Private/Get-ProjectCleanupPatterns.ps1 diff --git a/Private/Get-ProjectItemsToRemove.ps1 b/Module/Private/Get-ProjectItemsToRemove.ps1 similarity index 100% rename from Private/Get-ProjectItemsToRemove.ps1 rename to Module/Private/Get-ProjectItemsToRemove.ps1 diff --git a/Private/Get-RelativePath.ps1 b/Module/Private/Get-RelativePath.ps1 similarity index 100% rename from Private/Get-RelativePath.ps1 rename to Module/Private/Get-RelativePath.ps1 diff --git a/Private/Get-RequiredModule.ps1 b/Module/Private/Get-RequiredModule.ps1 similarity index 100% rename from Private/Get-RequiredModule.ps1 rename to Module/Private/Get-RequiredModule.ps1 diff --git a/Private/Get-RestMethodExceptionDetailsOrNull.ps1 b/Module/Private/Get-RestMethodExceptionDetailsOrNull.ps1 similarity index 100% rename from Private/Get-RestMethodExceptionDetailsOrNull.ps1 rename to Module/Private/Get-RestMethodExceptionDetailsOrNull.ps1 diff --git a/Private/Get-ScriptCommands.ps1 b/Module/Private/Get-ScriptCommands.ps1 similarity index 100% rename from Private/Get-ScriptCommands.ps1 rename to Module/Private/Get-ScriptCommands.ps1 diff --git a/Private/Get-ScriptsContentAndTryReplace.ps1 b/Module/Private/Get-ScriptsContentAndTryReplace.ps1 similarity index 100% rename from Private/Get-ScriptsContentAndTryReplace.ps1 rename to Module/Private/Get-ScriptsContentAndTryReplace.ps1 diff --git a/Private/Import-ValidCertificate.ps1 b/Module/Private/Import-ValidCertificate.ps1 similarity index 100% rename from Private/Import-ValidCertificate.ps1 rename to Module/Private/Import-ValidCertificate.ps1 diff --git a/Private/Initialize-InternalTests.ps1 b/Module/Private/Initialize-InternalTests.ps1 similarity index 100% rename from Private/Initialize-InternalTests.ps1 rename to Module/Private/Initialize-InternalTests.ps1 diff --git a/Private/Initialize-ReplacePath.ps1 b/Module/Private/Initialize-ReplacePath.ps1 similarity index 100% rename from Private/Initialize-ReplacePath.ps1 rename to Module/Private/Initialize-ReplacePath.ps1 diff --git a/Private/Invoke-ModuleTests.ps1 b/Module/Private/Invoke-ModuleTests.ps1 similarity index 100% rename from Private/Invoke-ModuleTests.ps1 rename to Module/Private/Invoke-ModuleTests.ps1 diff --git a/Private/Invoke-RestMethodAndThrowDescriptiveErrorOnFailure.ps1 b/Module/Private/Invoke-RestMethodAndThrowDescriptiveErrorOnFailure.ps1 similarity index 100% rename from Private/Invoke-RestMethodAndThrowDescriptiveErrorOnFailure.ps1 rename to Module/Private/Invoke-RestMethodAndThrowDescriptiveErrorOnFailure.ps1 diff --git a/Private/Merge-Module.ps1 b/Module/Private/Merge-Module.ps1 similarity index 100% rename from Private/Merge-Module.ps1 rename to Module/Private/Merge-Module.ps1 diff --git a/Private/New-DLLCodeOutput.ps1 b/Module/Private/New-DLLCodeOutput.ps1 similarity index 100% rename from Private/New-DLLCodeOutput.ps1 rename to Module/Private/New-DLLCodeOutput.ps1 diff --git a/Private/New-DLLHandleRuntime.ps1 b/Module/Private/New-DLLHandleRuntime.ps1 similarity index 100% rename from Private/New-DLLHandleRuntime.ps1 rename to Module/Private/New-DLLHandleRuntime.ps1 diff --git a/Private/New-DLLResolveConflict.ps1 b/Module/Private/New-DLLResolveConflict.ps1 similarity index 100% rename from Private/New-DLLResolveConflict.ps1 rename to Module/Private/New-DLLResolveConflict.ps1 diff --git a/Private/New-LibraryContent.ps1 b/Module/Private/New-LibraryContent.ps1 similarity index 100% rename from Private/New-LibraryContent.ps1 rename to Module/Private/New-LibraryContent.ps1 diff --git a/Private/New-PSMFile.ps1 b/Module/Private/New-PSMFile.ps1 similarity index 100% rename from Private/New-PSMFile.ps1 rename to Module/Private/New-PSMFile.ps1 diff --git a/Private/New-PersonalManifest.ps1 b/Module/Private/New-PersonalManifest.ps1 similarity index 84% rename from Private/New-PersonalManifest.ps1 rename to Module/Private/New-PersonalManifest.ps1 index e307e416..73cc2ea1 100644 --- a/Private/New-PersonalManifest.ps1 +++ b/Module/Private/New-PersonalManifest.ps1 @@ -99,7 +99,7 @@ function New-PersonalManifest { if ($Data.Path) { $Data.Remove('Path') } - $ValidateEntriesPrivateData = @('Tags', 'LicenseUri', 'ProjectURI', 'IconUri', 'ReleaseNotes', 'Prerelease', 'RequireLicenseAcceptance', 'ExternalModuleDependencies') + $ValidateEntriesPrivateData = @('Tags', 'LicenseUri', 'ProjectURI', 'IconUri', 'ReleaseNotes', 'Prerelease', 'RequireLicenseAcceptance', 'ExternalModuleDependencies', 'Delivery', 'Repository') foreach ($Entry in [string[]] $Data.Keys) { if ($Entry -in $ValidateEntriesPrivateData) { $Data.PrivateData.PSData.$Entry = $Data.$Entry @@ -124,6 +124,32 @@ function New-PersonalManifest { if ($Configuration.Steps.PublishModule.Prerelease) { $Data.PrivateData.PSData.Prerelease = $Configuration.Steps.PublishModule.Prerelease } + # Emit Delivery/Repository metadata (runtime-only) when provided + if ($Configuration.Options.Delivery -and $Configuration.Options.Delivery.Enable) { + $deliveryCfg = $Configuration.Options.Delivery + # Build runtime Delivery node + $deliveryNode = [ordered] @{ + InternalsPath = $deliveryCfg.InternalsPath + ImportantLinks = $deliveryCfg.ImportantLinks + IntroText = $deliveryCfg.IntroText + UpgradeText = $deliveryCfg.UpgradeText + IntroFile = $deliveryCfg.IntroFile + UpgradeFile = $deliveryCfg.UpgradeFile + DocumentationOrder = $deliveryCfg.DocumentationOrder + } + Remove-EmptyValue -Hashtable $deliveryNode + $Data.PrivateData.PSData.Delivery = $deliveryNode + + # Build Repository node (branch/paths only) + $repositoryNode = [ordered] @{ + Branch = $deliveryCfg.RepositoryBranch + Paths = $deliveryCfg.RepositoryPaths + } + Remove-EmptyValue -Hashtable $repositoryNode + if ($repositoryNode.Count -gt 0) { + $Data.PrivateData.PSData.Repository = $repositoryNode + } + } if ($TemporaryManifest.ExternalModuleDependencies) { # Add External Module Dependencies $Data.PrivateData.PSData.ExternalModuleDependencies = $TemporaryManifest.ExternalModuleDependencies @@ -164,4 +190,4 @@ function New-PersonalManifest { } $Data | Export-PSData -DataFile $ManifestPath -Sort } -} \ No newline at end of file +} diff --git a/Private/New-PrepareManifest.ps1 b/Module/Private/New-PrepareManifest.ps1 similarity index 100% rename from Private/New-PrepareManifest.ps1 rename to Module/Private/New-PrepareManifest.ps1 diff --git a/Private/New-PrepareStructure.ps1 b/Module/Private/New-PrepareStructure.ps1 similarity index 100% rename from Private/New-PrepareStructure.ps1 rename to Module/Private/New-PrepareStructure.ps1 diff --git a/Private/New-ProjectItemBackups.ps1 b/Module/Private/New-ProjectItemBackups.ps1 similarity index 100% rename from Private/New-ProjectItemBackups.ps1 rename to Module/Private/New-ProjectItemBackups.ps1 diff --git a/Private/Out-FileUft8NoBom.ps1 b/Module/Private/Out-FileUft8NoBom.ps1 similarity index 100% rename from Private/Out-FileUft8NoBom.ps1 rename to Module/Private/Out-FileUft8NoBom.ps1 diff --git a/Private/Register-DataForInitialModule.ps1 b/Module/Private/Register-DataForInitialModule.ps1 similarity index 100% rename from Private/Register-DataForInitialModule.ps1 rename to Module/Private/Register-DataForInitialModule.ps1 diff --git a/Private/Remove-ChildItems.ps1 b/Module/Private/Remove-ChildItems.ps1 similarity index 100% rename from Private/Remove-ChildItems.ps1 rename to Module/Private/Remove-ChildItems.ps1 diff --git a/Private/Remove-Directory.ps1 b/Module/Private/Remove-Directory.ps1 similarity index 100% rename from Private/Remove-Directory.ps1 rename to Module/Private/Remove-Directory.ps1 diff --git a/Private/Remove-EmptyLines.ps1 b/Module/Private/Remove-EmptyLines.ps1 similarity index 100% rename from Private/Remove-EmptyLines.ps1 rename to Module/Private/Remove-EmptyLines.ps1 diff --git a/Private/Remove-EmptyValue.ps1 b/Module/Private/Remove-EmptyValue.ps1 similarity index 100% rename from Private/Remove-EmptyValue.ps1 rename to Module/Private/Remove-EmptyValue.ps1 diff --git a/Private/Remove-FileItem.ps1 b/Module/Private/Remove-FileItem.ps1 similarity index 100% rename from Private/Remove-FileItem.ps1 rename to Module/Private/Remove-FileItem.ps1 diff --git a/Private/Remove-ItemAlternative.ps1 b/Module/Private/Remove-ItemAlternative.ps1 similarity index 100% rename from Private/Remove-ItemAlternative.ps1 rename to Module/Private/Remove-ItemAlternative.ps1 diff --git a/Private/Remove-ProjectItemsWithMethod.ps1 b/Module/Private/Remove-ProjectItemsWithMethod.ps1 similarity index 100% rename from Private/Remove-ProjectItemsWithMethod.ps1 rename to Module/Private/Remove-ProjectItemsWithMethod.ps1 diff --git a/Private/Repair-CustomPlaceHolders.ps1 b/Module/Private/Repair-CustomPlaceHolders.ps1 similarity index 100% rename from Private/Repair-CustomPlaceHolders.ps1 rename to Module/Private/Repair-CustomPlaceHolders.ps1 diff --git a/Module/Private/Resolve-DocFile.ps1 b/Module/Private/Resolve-DocFile.ps1 new file mode 100644 index 00000000..18798f9f --- /dev/null +++ b/Module/Private/Resolve-DocFile.ps1 @@ -0,0 +1,29 @@ +function Resolve-DocFile { + [CmdletBinding()] + param( + [Parameter(Mandatory)][ValidateSet('README','CHANGELOG','LICENSE','UPGRADE')] [string] $Kind, + [string] $RootBase, + [string] $InternalsBase, + [switch] $PreferInternals + ) + $root = $null; $intern = $null + $patterns = @() + switch ($Kind) { + 'README' { $patterns = @('README*') } + 'CHANGELOG' { $patterns = @('CHANGELOG*') } + 'LICENSE' { $patterns = @('LICENSE*','license.txt') } + 'UPGRADE' { $patterns = @('UPGRADE*','UPGRADING*','MIGRATION*') } + } + if ($RootBase) { + foreach ($p in $patterns) { + if (-not $root) { $root = Get-ChildItem -LiteralPath $RootBase -Filter $p -File -ErrorAction SilentlyContinue | Select-Object -First 1 } + } + } + if ($InternalsBase) { + foreach ($p in $patterns) { + if (-not $intern) { $intern = Get-ChildItem -LiteralPath $InternalsBase -Filter $p -File -ErrorAction SilentlyContinue | Select-Object -First 1 } + } + } + if ($PreferInternals) { if ($intern) { return $intern } else { return $root } } + else { if ($root) { return $root } else { return $intern } } +} diff --git a/Private/Resolve-Encoding.ps1 b/Module/Private/Resolve-Encoding.ps1 similarity index 100% rename from Private/Resolve-Encoding.ps1 rename to Module/Private/Resolve-Encoding.ps1 diff --git a/Private/Script.FormatterSettings.ps1 b/Module/Private/Script.FormatterSettings.ps1 similarity index 100% rename from Private/Script.FormatterSettings.ps1 rename to Module/Private/Script.FormatterSettings.ps1 diff --git a/Private/Send-FilesToGitHubRelease.ps1 b/Module/Private/Send-FilesToGitHubRelease.ps1 similarity index 100% rename from Private/Send-FilesToGitHubRelease.ps1 rename to Module/Private/Send-FilesToGitHubRelease.ps1 diff --git a/Private/Start-ArtefactsBuilding.ps1 b/Module/Private/Start-ArtefactsBuilding.ps1 similarity index 96% rename from Private/Start-ArtefactsBuilding.ps1 rename to Module/Private/Start-ArtefactsBuilding.ps1 index ab7713eb..cbbc10e8 100644 --- a/Private/Start-ArtefactsBuilding.ps1 +++ b/Module/Private/Start-ArtefactsBuilding.ps1 @@ -36,8 +36,8 @@ return } - $ModuleName = $Configuration.Information.ModuleName - $ModuleVersion = $Configuration.Information.Manifest.ModuleVersion + $ModuleName = $Configuration.Information.ModuleName + $ModuleVersion = $Configuration.Information.Manifest.ModuleVersion # Lets replace variables user may have used in paths $FullProjectPath = Initialize-ReplacePath -ReplacementPath $FullProjectPath -ModuleName $ModuleName -ModuleVersion $ModuleVersion -Configuration $Configuration @@ -59,6 +59,7 @@ # default values $FolderPathReleases = [System.IO.Path]::Combine($FullProjectPath, $Type) } + # Destination for the main module should be the artefact Path (not the modules path) if ($Artefact.RequiredModules.ModulesPath) { $DirectPathForPrimaryModule = $Artefact.RequiredModules.ModulesPath } elseif ($Artefact.RequiredModules.Path) { @@ -68,6 +69,7 @@ } else { $DirectPathForPrimaryModule = $FolderPathReleases } + # Destination for required modules is taken from RequiredModules.* or falls back to artefact Path if ($Artefact.RequiredModules.Path) { $DirectPathForRequiredModules = $Artefact.RequiredModules.Path } elseif ($Artefact.RequiredModules.ModulesPath) { @@ -152,4 +154,4 @@ } } } -ColorBefore Yellow -ColorTime Yellow -Color Yellow -} \ No newline at end of file +} diff --git a/Private/Start-DocumentationBuilding.ps1 b/Module/Private/Start-DocumentationBuilding.ps1 similarity index 100% rename from Private/Start-DocumentationBuilding.ps1 rename to Module/Private/Start-DocumentationBuilding.ps1 diff --git a/Private/Start-ImportingModules.ps1 b/Module/Private/Start-ImportingModules.ps1 similarity index 100% rename from Private/Start-ImportingModules.ps1 rename to Module/Private/Start-ImportingModules.ps1 diff --git a/Private/Start-LibraryBuilding.ps1 b/Module/Private/Start-LibraryBuilding.ps1 similarity index 93% rename from Private/Start-LibraryBuilding.ps1 rename to Module/Private/Start-LibraryBuilding.ps1 index 4c12231e..99d40b75 100644 --- a/Private/Start-LibraryBuilding.ps1 +++ b/Module/Private/Start-LibraryBuilding.ps1 @@ -107,11 +107,20 @@ foreach ($Framework in $TranslateFrameworks.Keys) { if ($SupportedFrameworks.Contains($Framework.ToLower()) -and $LibraryConfiguration.Framework.Contains($Framework.ToLower())) { Write-Text "[+] Building $Framework ($Configuration)" - $null = dotnet publish --configuration $Configuration --verbosity q -nologo -p:Version=$Version --framework $Framework + # Run dotnet publish and capture full stdout/stderr so we can show real errors on failure + $buildOutput = & dotnet publish --configuration $Configuration --verbosity minimal -nologo -p:Version=$Version --framework $Framework 2>&1 if ($LASTEXITCODE) { - Write-Host # This is to add new line, because the first line was opened up. + Write-Host # newline for readability Write-Text "[-] Building $Framework - failed. Error: $LASTEXITCODE" -Color Red - exit + if ($buildOutput) { + Write-Text " [-] dotnet publish output (first 100 lines):" -Color Red + $lines = @($buildOutput | Select-Object -First 100) + foreach ($line in $lines) { Write-Host " $line" } + if ($buildOutput.Count -gt 100) { + Write-Text " [...] output truncated (showing 100 of $($buildOutput.Count) lines)" -Color DarkYellow + } + } + exit $LASTEXITCODE } } else { continue @@ -260,4 +269,4 @@ Write-Text "[-] Couldn't switch back to the root folder. Error: $($_.Exception.Message)" -Color Red return $false } -} \ No newline at end of file +} diff --git a/Private/Start-ModuleBuilding.ps1 b/Module/Private/Start-ModuleBuilding.ps1 similarity index 100% rename from Private/Start-ModuleBuilding.ps1 rename to Module/Private/Start-ModuleBuilding.ps1 diff --git a/Private/Start-ModuleMerging.ps1 b/Module/Private/Start-ModuleMerging.ps1 similarity index 57% rename from Private/Start-ModuleMerging.ps1 rename to Module/Private/Start-ModuleMerging.ps1 index 76fdd0ca..226363b9 100644 --- a/Private/Start-ModuleMerging.ps1 +++ b/Module/Private/Start-ModuleMerging.ps1 @@ -29,6 +29,10 @@ } $LinkDirectoriesWithSupportFiles = $LinkDirectories | Where-Object { $_ -notin $CompareWorkaround } + # Additional guard: do not stage merge directories or their subpaths (Private/Public/Classes/Enums) + $LinkDirectoriesWithSupportFiles = $LinkDirectoriesWithSupportFiles | Where-Object { + $_ -notlike 'Private*' -and $_ -notlike 'Public*' -and $_ -notlike 'Classes*' -and $_ -notlike 'Enums*' + } foreach ($Directory in $LinkDirectoriesWithSupportFiles) { $Dir = [System.IO.Path]::Combine($FullModuleTemporaryPath, "$Directory") Add-Directory -Directory $Dir @@ -43,6 +47,26 @@ $FilesToLink = $LinkPrivatePublicFiles | Where-Object { $_ -notlike '*.ps1' -and $_ -notlike '*.psd1' } Copy-InternalFiles -LinkFiles $FilesToLink -FullModulePath $FullModuleTemporaryPath -FullProjectPath $FullProjectPath + # Copy non-merge PS1 files (e.g., Internals\Scripts\*.ps1) into the final module + foreach ($supportDir in $LinkDirectoriesWithSupportFiles) { + $dirTrim = $supportDir.TrimEnd([char]'/',[char]'\') + if ($dirTrim -notlike 'Internals*') { continue } + $glob = [System.IO.Path]::Combine($FullProjectPath, $dirTrim, '*.ps1') + $files = if ($PSEdition -eq 'Core') { + Get-ChildItem -Path $glob -ErrorAction SilentlyContinue -Recurse -FollowSymlink + } else { + Get-ChildItem -Path $glob -ErrorAction SilentlyContinue -Recurse + } + foreach ($file in $files) { + $rel = (Resolve-Path -LiteralPath $file.FullName -Relative) + if ($null -eq $IsWindows -or $IsWindows -eq $true) { $rel = $rel.Replace('.\\','') } else { $rel = $rel.Replace('./','') } + $relDir = [System.IO.Path]::GetDirectoryName($rel) + if ($relDir) { Add-Directory -Directory ([System.IO.Path]::Combine($FullModuleTemporaryPath, $relDir)) } + Copy-InternalFiles -LinkFiles @($rel) -FullModulePath $FullModuleTemporaryPath -FullProjectPath $FullProjectPath + } + } + + if ($Configuration.Information.LibrariesStandard) { # User provided option, we don't care } elseif ($Configuration.Information.LibrariesCore -and $Configuration.Information.LibrariesDefault) { @@ -159,6 +183,77 @@ return $false } + # If Delivery metadata is enabled, stage root README/CHANGELOG to requested destinations + if ($Configuration.Options -and $Configuration.Options.Delivery -and $Configuration.Options.Delivery.Enable) { + $internalsRel = if ($Configuration.Options.Delivery.InternalsPath) { [string]$Configuration.Options.Delivery.InternalsPath } else { 'Internals' } + if ($null -eq $IsWindows -or $IsWindows -eq $true) { + $internalsRel = $internalsRel.Replace('/', '\') + } else { + $internalsRel = $internalsRel.Replace('\\', '/') + } + $destInternals = [System.IO.Path]::Combine($FullModuleTemporaryPath, $internalsRel) + Add-Directory -Directory $destInternals + + $rootFiles = Get-ChildItem -Path $FullProjectPath -File -ErrorAction SilentlyContinue + $readmeDest = if ($Configuration.Options.Delivery.ReadmeDestination) { $Configuration.Options.Delivery.ReadmeDestination } else { 'Internals' } + $chlogDest = if ($Configuration.Options.Delivery.ChangelogDestination) { $Configuration.Options.Delivery.ChangelogDestination } else { 'Internals' } + $licDest = if ($Configuration.Options.Delivery.LicenseDestination) { $Configuration.Options.Delivery.LicenseDestination } else { 'Internals' } + + if ($rootFiles) { + foreach ($rf in $rootFiles) { + if ($rf.Name -like 'README*') { + switch ($readmeDest) { + 'Internals' { Copy-Item -LiteralPath $rf.FullName -Destination $destInternals -Force -ErrorAction SilentlyContinue } + 'Root' { Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath $rf.Name) -Force -ErrorAction SilentlyContinue } + 'Both' { + Copy-Item -LiteralPath $rf.FullName -Destination $destInternals -Force -ErrorAction SilentlyContinue + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath $rf.Name) -Force -ErrorAction SilentlyContinue + } + } + } elseif ($rf.Name -like 'CHANGELOG*') { + switch ($chlogDest) { + 'Internals' { Copy-Item -LiteralPath $rf.FullName -Destination $destInternals -Force -ErrorAction SilentlyContinue } + 'Root' { Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath $rf.Name) -Force -ErrorAction SilentlyContinue } + 'Both' { + Copy-Item -LiteralPath $rf.FullName -Destination $destInternals -Force -ErrorAction SilentlyContinue + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath $rf.Name) -Force -ErrorAction SilentlyContinue + } + } + } elseif ($rf.Name -like 'LICENSE*') { + switch ($licDest) { + 'Internals' { + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $destInternals 'license.txt') -Force -ErrorAction SilentlyContinue + } + 'Root' { + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath 'license.txt') -Force -ErrorAction SilentlyContinue + } + 'Both' { + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $destInternals 'license.txt') -Force -ErrorAction SilentlyContinue + Copy-Item -LiteralPath $rf.FullName -Destination (Join-Path $FullModuleTemporaryPath 'license.txt') -Force -ErrorAction SilentlyContinue + } + } + } + } + # Enforce root license.txt when RequireLicenseAcceptance is true + $requireAccept = $false + if ($Configuration.Information.Manifest.RequireLicenseAcceptance) { $requireAccept = $true } + if ($requireAccept) { + # If no license.txt present at root, but license exists under rootFiles or Internals, ensure root license.txt + $existingRootLicense = Join-Path $FullModuleTemporaryPath 'license.txt' + if (-not (Test-Path -LiteralPath $existingRootLicense)) { + $sourceLic = ($rootFiles | Where-Object { $_.Name -like 'LICENSE*' } | Select-Object -First 1) + if (-not $sourceLic -and (Test-Path -LiteralPath $destInternals)) { + $cand = Get-ChildItem -LiteralPath $destInternals -Filter 'LICENSE*' -File -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($cand) { $sourceLic = $cand } + } + if ($sourceLic) { + Copy-Item -LiteralPath $sourceLic.FullName -Destination $existingRootLicense -Force -ErrorAction SilentlyContinue + } + } + } + } + } + if ($Configuration.Steps.BuildModule.CreateFileCatalog) { # Something is wrong here for folders other than root, need investigation $TimeToExecuteSign = [System.Diagnostics.Stopwatch]::StartNew() @@ -195,4 +290,4 @@ Copy-InternalFiles -LinkFiles $LinkPrivatePublicFiles -FullModulePath $FullModuleTemporaryPath -FullProjectPath $FullProjectPath Write-Text -End -Time $LinkingFilesTime } -} \ No newline at end of file +} diff --git a/Private/Start-ModuleSigning.ps1 b/Module/Private/Start-ModuleSigning.ps1 similarity index 69% rename from Private/Start-ModuleSigning.ps1 rename to Module/Private/Start-ModuleSigning.ps1 index 543d7362..5561dad8 100644 --- a/Private/Start-ModuleSigning.ps1 +++ b/Module/Private/Start-ModuleSigning.ps1 @@ -11,7 +11,7 @@ WarningVariable = 'Warnings' LocalStore = 'CurrentUser' Path = $FullModuleTemporaryPath - Include = @('*.ps1', '*.psd1', '*.psm1', '*.dll', '*.cat') + # Include list will be determined below TimeStampServer = 'http://timestamp.digicert.com' } @@ -37,6 +37,32 @@ $registerCertificateSplat.Thumbprint = $Configuration.Options.Signing.CertificateThumbprint } } + # Build include patterns with safe defaults (scripts only) + if ($Configuration.Options.Signing -and $Configuration.Options.Signing.Include) { + $registerCertificateSplat.Include = @($Configuration.Options.Signing.Include) + } else { + $include = @('*.ps1','*.psm1','*.psd1') + if ($Configuration.Options.Signing -and $Configuration.Options.Signing.IncludeBinaries) { + $include += @('*.dll','*.cat') + } + if ($Configuration.Options.Signing -and $Configuration.Options.Signing.IncludeExe) { + $include += @('*.exe') + } + $registerCertificateSplat.Include = $include + } + + # Exclude Internals unless explicitly enabled + $excludePaths = @() + if (-not ($Configuration.Options.Signing -and $Configuration.Options.Signing.IncludeInternals)) { + $excludePaths += 'Internals' + } + if ($Configuration.Options.Signing -and $Configuration.Options.Signing.ExcludePaths) { + $excludePaths += @($Configuration.Options.Signing.ExcludePaths) + } + if ($excludePaths.Count -gt 0) { + $registerCertificateSplat.ExcludePath = $excludePaths + } + [Array] $SignedFiles = Register-Certificate @registerCertificateSplat if ($Warnings) { foreach ($W in $Warnings) { @@ -63,4 +89,4 @@ } } -PreAppend Plus } -} \ No newline at end of file +} diff --git a/Private/Start-PreparingFunctionsAndAliases.ps1 b/Module/Private/Start-PreparingFunctionsAndAliases.ps1 similarity index 100% rename from Private/Start-PreparingFunctionsAndAliases.ps1 rename to Module/Private/Start-PreparingFunctionsAndAliases.ps1 diff --git a/Private/Start-PreparingStructure.ps1 b/Module/Private/Start-PreparingStructure.ps1 similarity index 100% rename from Private/Start-PreparingStructure.ps1 rename to Module/Private/Start-PreparingStructure.ps1 diff --git a/Private/Start-PreparingVariables.ps1 b/Module/Private/Start-PreparingVariables.ps1 similarity index 75% rename from Private/Start-PreparingVariables.ps1 rename to Module/Private/Start-PreparingVariables.ps1 index 363c60d7..10147175 100644 --- a/Private/Start-PreparingVariables.ps1 +++ b/Module/Private/Start-PreparingVariables.ps1 @@ -58,27 +58,34 @@ } $Path = [io.path]::Combine($FullProjectPath, '*') - if ($PSEdition -eq 'core') { - $Directories = @( - $TempDirectories = Get-ChildItem -Path $FullProjectPath -Directory -Exclude $Exclude -FollowSymlink - @( - $TempDirectories - $TempDirectories | Get-ChildItem -Directory -Recurse -FollowSymlink - ) - ) - $Files = Get-ChildItem -Path $FullProjectPath -Exclude $Exclude -FollowSymlink | Get-ChildItem -File -Recurse -FollowSymlink - $FilesRoot = Get-ChildItem -Path $Path -Include $IncludeFilesRoot -File -FollowSymlink - } else { - $Directories = @( - $TempDirectories = Get-ChildItem -Path $FullProjectPath -Directory -Exclude $Exclude - @( - $TempDirectories - $TempDirectories | Get-ChildItem -Directory -Recurse - ) - ) - $Files = Get-ChildItem -Path $FullProjectPath -Exclude $Exclude | Get-ChildItem -File -Recurse - $FilesRoot = Get-ChildItem -Path $Path -Include $IncludeFilesRoot -File + # Scan only relevant directories (PS1, Classes, user arrays, IncludeAll) with pruning + $ScanDirs = @( + $DirectoriesWithPS1 + $DirectoriesWithClasses + $DirectoriesWithArrays + $DirectoriesWithAll + ) + $ScanDirs = $ScanDirs | Where-Object { $_ -and -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique + + $PruneNames = @('.git', 'obj', 'bin', '.vs', 'node_modules', 'dist', 'out', 'Ignore') + foreach ($ex in $Exclude) { + if ($ex -is [string]) { + $n = [IO.Path]::GetFileName($ex) + if ($n -and $PruneNames -notcontains $n) { $PruneNames += $n } + } } + + # Do not globally prune 'Docs' when the build explicitly includes 'Internals\' via IncludeAll. + # Otherwise Internals\Docs would be skipped and not bundled. + if ($Exclude) { $Exclude = $Exclude | Where-Object { $_ -ne 'Docs' } } + if ($DirectoriesWithAll -and ($DirectoriesWithAll | Where-Object { $_ -match '^(?i)internals[\\/]+$|^(?i)internals[\\/]' })) { + $PruneNames = $PruneNames | Where-Object { $_ -ne 'Docs' } + } + + $FollowSymlink = $false + $Directories = Get-PSPDirectoriesPruned -BasePath $FullProjectPath -ScanRelativeDirs $ScanDirs -ExcludeNames $Exclude -PruneNames $PruneNames -FollowSymlink:$FollowSymlink + $Files = Get-PSPFilesPruned -Directories $Directories -FollowSymlink:$FollowSymlink + $FilesRoot = Get-ChildItem -Path $Path -Include $IncludeFilesRoot -File -ErrorAction SilentlyContinue $LinkDirectories = @( foreach ($Directory in $Directories) { if ($null -eq $IsWindows -or $IsWindows -eq $true) { @@ -156,6 +163,15 @@ } continue } + default { + # Include files without extension from directories requested via IncludeAll (e.g., Internals) + foreach ($dir in $DirectoriesWithAll) { + if ($file -like "$dir*") { + $file + } + } + continue + } } } ) @@ -170,4 +186,4 @@ DirectoriesWithPS1 = $DirectoriesWithPS1 } } -} \ No newline at end of file +} diff --git a/Private/Start-PublishingGallery.ps1 b/Module/Private/Start-PublishingGallery.ps1 similarity index 100% rename from Private/Start-PublishingGallery.ps1 rename to Module/Private/Start-PublishingGallery.ps1 diff --git a/Private/Start-PublishingGitHub.ps1 b/Module/Private/Start-PublishingGitHub.ps1 similarity index 100% rename from Private/Start-PublishingGitHub.ps1 rename to Module/Private/Start-PublishingGitHub.ps1 diff --git a/Private/Step-Version.ps1 b/Module/Private/Step-Version.ps1 similarity index 100% rename from Private/Step-Version.ps1 rename to Module/Private/Step-Version.ps1 diff --git a/Private/Test-AllFilePathsAndThrowErrorIfOneIsNotValid.ps1 b/Module/Private/Test-AllFilePathsAndThrowErrorIfOneIsNotValid.ps1 similarity index 100% rename from Private/Test-AllFilePathsAndThrowErrorIfOneIsNotValid.ps1 rename to Module/Private/Test-AllFilePathsAndThrowErrorIfOneIsNotValid.ps1 diff --git a/Private/Test-Basic.ps1 b/Module/Private/Test-Basic.ps1 similarity index 100% rename from Private/Test-Basic.ps1 rename to Module/Private/Test-Basic.ps1 diff --git a/Private/Test-ExcludedPath.ps1 b/Module/Private/Test-ExcludedPath.ps1 similarity index 100% rename from Private/Test-ExcludedPath.ps1 rename to Module/Private/Test-ExcludedPath.ps1 diff --git a/Private/Test-ModuleImport.ps1 b/Module/Private/Test-ModuleImport.ps1 similarity index 100% rename from Private/Test-ModuleImport.ps1 rename to Module/Private/Test-ModuleImport.ps1 diff --git a/Private/Test-ReparsePoint.ps1 b/Module/Private/Test-ReparsePoint.ps1 similarity index 100% rename from Private/Test-ReparsePoint.ps1 rename to Module/Private/Test-ReparsePoint.ps1 diff --git a/Private/Test-RequiredModules.ps1 b/Module/Private/Test-RequiredModules.ps1 similarity index 100% rename from Private/Test-RequiredModules.ps1 rename to Module/Private/Test-RequiredModules.ps1 diff --git a/Private/Test-ScriptFile.ps1 b/Module/Private/Test-ScriptFile.ps1 similarity index 100% rename from Private/Test-ScriptFile.ps1 rename to Module/Private/Test-ScriptFile.ps1 diff --git a/Private/Test-ScriptModule.ps1 b/Module/Private/Test-ScriptModule.ps1 similarity index 100% rename from Private/Test-ScriptModule.ps1 rename to Module/Private/Test-ScriptModule.ps1 diff --git a/Private/Update-VersionInBuildScript.ps1 b/Module/Private/Update-VersionInBuildScript.ps1 similarity index 100% rename from Private/Update-VersionInBuildScript.ps1 rename to Module/Private/Update-VersionInBuildScript.ps1 diff --git a/Private/Update-VersionInCsProj.ps1 b/Module/Private/Update-VersionInCsProj.ps1 similarity index 100% rename from Private/Update-VersionInCsProj.ps1 rename to Module/Private/Update-VersionInCsProj.ps1 diff --git a/Private/Update-VersionInPsd1.ps1 b/Module/Private/Update-VersionInPsd1.ps1 similarity index 100% rename from Private/Update-VersionInPsd1.ps1 rename to Module/Private/Update-VersionInPsd1.ps1 diff --git a/Private/Update-VersionNumber.ps1 b/Module/Private/Update-VersionNumber.ps1 similarity index 100% rename from Private/Update-VersionNumber.ps1 rename to Module/Private/Update-VersionNumber.ps1 diff --git a/Module/Private/Write-Heading.ps1 b/Module/Private/Write-Heading.ps1 new file mode 100644 index 00000000..c9dcbc3f --- /dev/null +++ b/Module/Private/Write-Heading.ps1 @@ -0,0 +1,8 @@ +function Write-Heading { + [CmdletBinding()] + param([Parameter(Mandatory)][string] $Text) + Write-Host ('=' * $Text.Length) -ForegroundColor DarkGray + Write-Host $Text -ForegroundColor Cyan + Write-Host ('=' * $Text.Length) -ForegroundColor DarkGray +} + diff --git a/Private/Write-ModuleTestDetails.ps1 b/Module/Private/Write-ModuleTestDetails.ps1 similarity index 100% rename from Private/Write-ModuleTestDetails.ps1 rename to Module/Private/Write-ModuleTestDetails.ps1 diff --git a/Private/Write-ModuleTestSummary.ps1 b/Module/Private/Write-ModuleTestSummary.ps1 similarity index 100% rename from Private/Write-ModuleTestSummary.ps1 rename to Module/Private/Write-ModuleTestSummary.ps1 diff --git a/Private/Write-PowerShellHashTable.ps1 b/Module/Private/Write-PowerShellHashTable.ps1 similarity index 100% rename from Private/Write-PowerShellHashTable.ps1 rename to Module/Private/Write-PowerShellHashTable.ps1 diff --git a/Private/Write-Text.ps1 b/Module/Private/Write-Text.ps1 similarity index 100% rename from Private/Write-Text.ps1 rename to Module/Private/Write-Text.ps1 diff --git a/Private/Write-TextWithTime.ps1 b/Module/Private/Write-TextWithTime.ps1 similarity index 100% rename from Private/Write-TextWithTime.ps1 rename to Module/Private/Write-TextWithTime.ps1 diff --git a/Public/Convert-ProjectEncoding.ps1 b/Module/Public/Convert-ProjectEncoding.ps1 similarity index 100% rename from Public/Convert-ProjectEncoding.ps1 rename to Module/Public/Convert-ProjectEncoding.ps1 diff --git a/Public/Convert-ProjectLineEnding.ps1 b/Module/Public/Convert-ProjectLineEnding.ps1 similarity index 100% rename from Public/Convert-ProjectLineEnding.ps1 rename to Module/Public/Convert-ProjectLineEnding.ps1 diff --git a/Public/Export-CertificateForNuGet.ps1 b/Module/Public/Export-CertificateForNuGet.ps1 similarity index 100% rename from Public/Export-CertificateForNuGet.ps1 rename to Module/Public/Export-CertificateForNuGet.ps1 diff --git a/Public/Get-MissingFunctions.ps1 b/Module/Public/Get-MissingFunctions.ps1 similarity index 63% rename from Public/Get-MissingFunctions.ps1 rename to Module/Public/Get-MissingFunctions.ps1 index a43a93fd..d0e24f6a 100644 --- a/Public/Get-MissingFunctions.ps1 +++ b/Module/Public/Get-MissingFunctions.ps1 @@ -1,4 +1,47 @@ function Get-MissingFunctions { + <# + .SYNOPSIS + Analyzes a script or scriptblock and reports functions it calls that are not present. + + .DESCRIPTION + Scans the provided file path or scriptblock, detects referenced commands, filters them down to + function calls, and returns a summary or the raw helper function definitions that can be inlined. + When -ApprovedModules is specified, helper definitions are only taken from those modules; otherwise + only the list is returned. Use this to build self-contained scripts by discovering dependencies. + + .PARAMETER FilePath + Path to a script file to analyze for missing function dependencies. Alias: Path. + + .PARAMETER Code + ScriptBlock to analyze instead of a file. Alias: ScriptBlock. + + .PARAMETER Functions + Known function names to treat as already available (exclude from missing list). + + .PARAMETER Summary + Return only a flattened summary list of functions used (objects with Name/Source), not inlined definitions. + + .PARAMETER SummaryWithCommands + Return a hashtable with Summary (names), SummaryFiltered (objects), and Functions (inlineable text). + + .PARAMETER ApprovedModules + Module names that are allowed sources for pulling inline helper function definitions. + + .PARAMETER IgnoreFunctions + Function names to ignore when computing the missing set. + + .EXAMPLE + Get-MissingFunctions -FilePath .\Build\Manage-Module.ps1 -Summary + Returns a list of functions used by the script. + + .EXAMPLE + $sb = { Invoke-ModuleBuild -ModuleName 'MyModule' } + Get-MissingFunctions -Code $sb -SummaryWithCommands -ApprovedModules 'PSSharedGoods','PSPublishModule' + Returns a hashtable with a summary and inlineable helper definitions sourced from approved modules. + + .NOTES + Use with Initialize-PortableScript to emit a self-contained version of a script. + #> [CmdletBinding()] param( [alias('Path')][string] $FilePath, @@ -84,4 +127,4 @@ } else { return $FunctionsOutput } -} \ No newline at end of file +} diff --git a/Public/Get-ModuleInformation.ps1 b/Module/Public/Get-ModuleInformation.ps1 similarity index 100% rename from Public/Get-ModuleInformation.ps1 rename to Module/Public/Get-ModuleInformation.ps1 diff --git a/Public/Get-ModuleTestFailures.ps1 b/Module/Public/Get-ModuleTestFailures.ps1 similarity index 100% rename from Public/Get-ModuleTestFailures.ps1 rename to Module/Public/Get-ModuleTestFailures.ps1 diff --git a/Public/Get-PowerShellAssemblyMetaData.ps1 b/Module/Public/Get-PowerShellAssemblyMetaData.ps1 similarity index 100% rename from Public/Get-PowerShellAssemblyMetaData.ps1 rename to Module/Public/Get-PowerShellAssemblyMetaData.ps1 diff --git a/Public/Get-PowerShellCompatibility.ps1 b/Module/Public/Get-PowerShellCompatibility.ps1 similarity index 100% rename from Public/Get-PowerShellCompatibility.ps1 rename to Module/Public/Get-PowerShellCompatibility.ps1 diff --git a/Public/Get-ProjectConsistency.ps1 b/Module/Public/Get-ProjectConsistency.ps1 similarity index 100% rename from Public/Get-ProjectConsistency.ps1 rename to Module/Public/Get-ProjectConsistency.ps1 diff --git a/Public/Get-ProjectEncoding.ps1 b/Module/Public/Get-ProjectEncoding.ps1 similarity index 100% rename from Public/Get-ProjectEncoding.ps1 rename to Module/Public/Get-ProjectEncoding.ps1 diff --git a/Public/Get-ProjectLineEnding.ps1 b/Module/Public/Get-ProjectLineEnding.ps1 similarity index 100% rename from Public/Get-ProjectLineEnding.ps1 rename to Module/Public/Get-ProjectLineEnding.ps1 diff --git a/Public/Get-ProjectVersion.ps1 b/Module/Public/Get-ProjectVersion.ps1 similarity index 100% rename from Public/Get-ProjectVersion.ps1 rename to Module/Public/Get-ProjectVersion.ps1 diff --git a/Public/Initialize-PortableModule.ps1 b/Module/Public/Initialize-PortableModule.ps1 similarity index 67% rename from Public/Initialize-PortableModule.ps1 rename to Module/Public/Initialize-PortableModule.ps1 index fe27640d..b1e684f2 100644 --- a/Public/Initialize-PortableModule.ps1 +++ b/Module/Public/Initialize-PortableModule.ps1 @@ -1,4 +1,37 @@ function Initialize-PortableModule { + <# + .SYNOPSIS + Downloads and/or imports a module and its dependencies as a portable set. + + .DESCRIPTION + Assists in preparing a portable environment for a module by either downloading it (plus dependencies) + to a specified path, importing those modules from disk, or both. Generates a convenience script that + imports all discovered module manifests when -Download is used. + + .PARAMETER Name + Name of the module to download/import. Alias: ModuleName. + + .PARAMETER Path + Filesystem path where modules are saved or imported from. Defaults to the current script root. + + .PARAMETER Download + Save the module and its dependencies to the specified path. + + .PARAMETER Import + Import the module and its dependencies from the specified path. + + .EXAMPLE + Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Download + Saves the module and its dependencies into C:\Portable. + + .EXAMPLE + Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Import + Imports the module and its dependencies from C:\Portable. + + .EXAMPLE + Initialize-PortableModule -Name 'EFAdminManager' -Path 'C:\Portable' -Download -Import + Saves and then imports the module and dependencies, and creates a helper script. + #> [CmdletBinding()] param( [alias('ModuleName')][string] $Name, @@ -78,4 +111,4 @@ Import-Module $_ -Verbose:$false -Force } } -} \ No newline at end of file +} diff --git a/Module/Public/Initialize-PortableScript.ps1 b/Module/Public/Initialize-PortableScript.ps1 new file mode 100644 index 00000000..5f5a9be5 --- /dev/null +++ b/Module/Public/Initialize-PortableScript.ps1 @@ -0,0 +1,48 @@ +function Initialize-PortableScript { + <# + .SYNOPSIS + Produces a self-contained script by inlining missing helper function definitions. + + .DESCRIPTION + Analyzes the input script for function calls not present in the script itself, pulls helper + definitions from approved modules, and writes a combined output file that begins with those + helper definitions followed by the original script content. Useful for portable delivery. + + .PARAMETER FilePath + Path to the source script to analyze and convert. + + .PARAMETER OutputPath + Destination path for the generated self-contained script. + + .PARAMETER ApprovedModules + Module names that are permitted sources for inlined helper functions. + + .EXAMPLE + Initialize-PortableScript -FilePath .\Scripts\Do-Work.ps1 -OutputPath .\Artefacts\Do-Work.Portable.ps1 -ApprovedModules PSSharedGoods + Generates a portable script with helper functions inlined at the top. + + .NOTES + Output encoding is UTF8BOM on PS 7+, UTF8 on PS 5.1 for compatibility. + #> + [cmdletBinding()] + param( + [string] $FilePath, + [string] $OutputPath, + [Array] $ApprovedModules + ) + + if ($PSVersionTable.PSVersion.Major -gt 5) { + $Encoding = 'UTF8BOM' + } else { + $Encoding = 'UTF8' + } + + $Output = Get-MissingFunctions -FilePath $FilePath -SummaryWithCommands -ApprovedModules $ApprovedModules + $Script = Get-Content -LiteralPath $FilePath -Encoding UTF8 + $FinalScript = @( + $Output.Functions + $Script + ) + $FinalScript | Set-Content -LiteralPath $OutputPath -Encoding $Encoding + $Output +} diff --git a/Public/Initialize-ProjectManager.ps1 b/Module/Public/Initialize-ProjectManager.ps1 similarity index 100% rename from Public/Initialize-ProjectManager.ps1 rename to Module/Public/Initialize-ProjectManager.ps1 diff --git a/Module/Public/Install-ProjectDocumentation.ps1 b/Module/Public/Install-ProjectDocumentation.ps1 new file mode 100644 index 00000000..2387c65d --- /dev/null +++ b/Module/Public/Install-ProjectDocumentation.ps1 @@ -0,0 +1,316 @@ +function Install-ProjectDocumentation { + <# + .SYNOPSIS + Installs bundled module documentation/examples (Internals) to a chosen path. + + .DESCRIPTION + Copies the contents of a module's Internals folder (or the path defined in + PrivateData.PSData.Delivery) to a destination outside of + $env:PSModulePath, including subfolders such as Scripts, Docs, Binaries, Config. + When -IncludeRootReadme/-IncludeRootChangelog/-IncludeRootLicense are enabled in + New-ConfigurationDelivery, root README/CHANGELOG/LICENSE are also copied. + + .PARAMETER Name + Module name to install documentation for. Accepts pipeline by value. + + .PARAMETER RequiredVersion + Specific version of the module to target. If omitted, selects the highest available. + + .PARAMETER Module + A PSModuleInfo object (e.g., from Get-Module -ListAvailable) to operate on directly. + + .PARAMETER Path + Destination directory where the Internals content will be copied. + + .PARAMETER Layout + How to lay out the destination path: + - Direct: copy into + - Module: copy into \\ + - ModuleAndVersion (default): copy into \\\\ + + .PARAMETER OnExists + What to do if the destination folder already exists: + - Merge (default): merge files/folders; overwrite files only when -Force is used + - Overwrite: remove the existing destination, then copy fresh + - Skip: do nothing and return the existing destination path + - Stop: throw an error + + .PARAMETER CreateVersionSubfolder + When set (default), content is placed under '\\\\'. + If disabled, content is copied directly into ''. + + .PARAMETER Force + Overwrite existing files. + + .PARAMETER ListOnly + Show what would be copied and where, without copying any files. Returns the + computed destination path(s). Use -Verbose for details. + + .PARAMETER Open + After a successful copy, open the README in the destination (if present). + + .PARAMETER NoIntro + Suppress introductory notes and important links printed after installation. + + .EXAMPLE + Install-ProjectDocumentation -Name AdminManager -Path 'C:\Docs' + + .EXAMPLE + Get-Module -ListAvailable AdminManager | Install-ProjectDocumentation -Path 'D:\\AM' + Installs the highest available version of AdminManager to D:\AM\AdminManager\ + + .EXAMPLE + # Copy into Path\Name only, merge on re-run without overwriting existing files + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -Layout Module + + .EXAMPLE + # Overwrite destination on re-run + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -OnExists Overwrite + + .EXAMPLE + # Dry-run: show what would be copied and where + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -ListOnly -Verbose + + .EXAMPLE + # Copy, suppress intro/links printing, and open README afterwards + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\Docs' -NoIntro -Open + + .EXAMPLE + # Typical build time configuration + New-ConfigurationInformation -IncludeAll 'Internals\' + New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -DocumentationOrder '01-Intro.md','02-HowTo.md' -IncludeRootReadme -IncludeRootChangelog + + .EXAMPLE + # Direct layout into target folder (no Module/Version subfolders) + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -Layout Direct + + .EXAMPLE + # Copy into C:\\Docs\\EFAdminManager and merge on rerun (only overwrite when -Force) + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -Layout Module -OnExists Merge -Force + + .EXAMPLE + # Overwrite destination entirely on rerun + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -OnExists Overwrite + + .EXAMPLE + # Skip if destination exists + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -OnExists Skip + + .EXAMPLE + # Plan only with verbose output + Install-ProjectDocumentation -Name EFAdminManager -Path 'C:\\Docs' -ListOnly -Verbose + #> + [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByName')] + param( + [Parameter(ParameterSetName = 'ByName', Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] + [Alias('ModuleName')] + [string] $Name, + [Parameter(ParameterSetName = 'ByModule', ValueFromPipeline = $true)] + [Alias('InputObject', 'ModuleInfo')] + [System.Management.Automation.PSModuleInfo] $Module, + [version] $RequiredVersion, + [Parameter(Mandatory)] + [string] $Path, + [ValidateSet('Direct', 'Module', 'ModuleAndVersion')] + [string] $Layout = 'ModuleAndVersion', + [ValidateSet('Merge', 'Overwrite', 'Skip', 'Stop')] + [string] $OnExists = 'Merge', + [switch] $CreateVersionSubfolder, # legacy toggle: if bound and Layout not specified, maps to Direct/ModuleAndVersion + [switch] $Force, + [switch] $ListOnly, + [switch] $Open, + [switch] $NoIntro + ) + + begin { + # Use a generic list for performance/compat across PS5/PS7 + $resolvedTargets = [System.Collections.Generic.List[string]]::new() + } + process { + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + if (-not $Name) { throw "Specify -Name or provide a module via the pipeline." } + $candidates = Get-Module -ListAvailable -Name $Name + if (-not $candidates) { throw "Module '$Name' not found." } + if ($RequiredVersion) { + $Module = $candidates | Where-Object { $_.Version -eq $RequiredVersion } | Sort-Object Version -Descending | Select-Object -First 1 + if (-not $Module) { throw "Module '$Name' with version $RequiredVersion not found." } + } else { + $Module = $candidates | Sort-Object Version -Descending | Select-Object -First 1 + } + } elseif ($PSCmdlet.ParameterSetName -eq 'ByModule') { + if (-not $Module) { throw "Pipeline didn't pass a PSModuleInfo object. Use -Name or pipe Get-Module output." } + if ($RequiredVersion -and $Module.Version -ne $RequiredVersion) { + # Try to resolve the exact version if requested differs from piped object + $resolved = Get-Module -ListAvailable -Name $Module.Name | Where-Object { $_.Version -eq $RequiredVersion } | Sort-Object Version -Descending | Select-Object -First 1 + if ($resolved) { $Module = $resolved } else { throw "Module '$($Module.Name)' with version $RequiredVersion not found." } + } + } + + $manifestPath = Join-Path $Module.ModuleBase ("{0}.psd1" -f $Module.Name) + if (-not (Test-Path -LiteralPath $manifestPath)) { + throw "Manifest not found for module '$($Module.Name)' at '$manifestPath'." + } + + $manifest = Test-ModuleManifest -Path $manifestPath + $delivery = $manifest.PrivateData.PSData.Delivery + + $internalsRel = if ($delivery -and $delivery.InternalsPath) { [string]$delivery.InternalsPath } else { 'Internals' } + $includeReadme = if ($null -ne $delivery.IncludeRootReadme) { [bool]$delivery.IncludeRootReadme } else { $true } + $includeChlog = if ($null -ne $delivery.IncludeRootChangelog) { [bool]$delivery.IncludeRootChangelog } else { $true } + $includeLicense = if ($null -ne $delivery.IncludeRootLicense) { [bool]$delivery.IncludeRootLicense } else { $true } + + $internalsPath = Join-Path $Module.ModuleBase $internalsRel + if (-not (Test-Path -LiteralPath $internalsPath)) { + throw "Internals path '$internalsRel' not found under module base '$($Module.ModuleBase)'." + } + + # Back-compat: if legacy CreateVersionSubfolder was provided and Layout not changed, honor it + if ($PSBoundParameters.ContainsKey('CreateVersionSubfolder') -and -not $PSBoundParameters.ContainsKey('Layout')) { + $Layout = if ($CreateVersionSubfolder) { 'ModuleAndVersion' } else { 'Direct' } + } + + switch ($Layout) { + 'Direct' { $dest = $Path } + 'Module' { $dest = Join-Path $Path $Module.Name } + 'ModuleAndVersion' { $dest = Join-Path (Join-Path $Path $Module.Name) $Module.Version.ToString() } + } + + # If listing only, do not copy - just output the planned destination + if ($ListOnly) { + Write-Verbose "Would copy Internals from '$internalsPath' to '$dest' using Layout=$Layout, OnExists=$OnExists." + $resolvedTargets.Add($dest) + return + } + + if ($PSCmdlet.ShouldProcess("$internalsPath", "Copy to '$dest'")) { + $exists = Test-Path -LiteralPath $dest + if ($exists) { + switch ($OnExists) { + 'Skip' { $resolvedTargets.Add($dest); return } + 'Stop' { throw "Destination '$dest' already exists." } + 'Overwrite' { + Remove-Item -LiteralPath $dest -Recurse -Force -ErrorAction SilentlyContinue + New-Item -ItemType Directory -Path $dest -Force | Out-Null + Copy-PSPDirectoryTree -Source $internalsPath -Destination $dest -Overwrite:$true + } + 'Merge' { + Copy-PSPDirectoryTree -Source $internalsPath -Destination $dest -Overwrite:$Force.IsPresent + } + } + } else { + New-Item -ItemType Directory -Path $dest -Force | Out-Null + Copy-PSPDirectoryTree -Source $internalsPath -Destination $dest -Overwrite:$Force.IsPresent + } + + # Copy selected root files from module base in a PS5/PS7-safe, readable way + $rootFiles = @(Get-ChildItem -Path $Module.ModuleBase -File -ErrorAction SilentlyContinue) + + if ($includeReadme -and $rootFiles.Count -gt 0) { + foreach ($file in $rootFiles) { + if ($file.Name -like 'README*') { + try { Copy-Item -LiteralPath $file.FullName -Destination $dest -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + } + if ($includeChlog -and $rootFiles.Count -gt 0) { + foreach ($file in $rootFiles) { + if ($file.Name -like 'CHANGELOG*') { + try { Copy-Item -LiteralPath $file.FullName -Destination $dest -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + } + if ($includeLicense -and $rootFiles.Count -gt 0) { + foreach ($file in $rootFiles) { + if ($file.Name -like 'LICENSE*') { + try { Copy-Item -LiteralPath $file.FullName -Destination (Join-Path $dest 'license.txt') -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + } + + # Copy Intro/Upgrade files if explicitly provided in delivery metadata + if ($delivery) { + if ($delivery.IntroFile) { + $introSrc = Join-Path $Module.ModuleBase ([string]$delivery.IntroFile) + if (Test-Path -LiteralPath $introSrc) { + try { Copy-Item -LiteralPath $introSrc -Destination $dest -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + if ($delivery.UpgradeFile) { + $upgradeSrc = Join-Path $Module.ModuleBase ([string]$delivery.UpgradeFile) + if (Test-Path -LiteralPath $upgradeSrc) { + try { Copy-Item -LiteralPath $upgradeSrc -Destination $dest -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + } + if ($includeLicense -and $rootFiles.Count -gt 0) { + foreach ($file in $rootFiles) { + if ($file.Name -like 'LICENSE*') { + try { Copy-Item -LiteralPath $file.FullName -Destination $dest -Force:$Force.IsPresent -ErrorAction Stop } catch { } + } + } + } + + $resolvedTargets.Add($dest) + + # Intro and links (unless suppressed) + if (-not $NoIntro) { + $hasIntro = $false + if ($delivery) { + if ($delivery.IntroText) { + $hasIntro = $true + Write-Host '' + Write-Host 'Introduction:' -ForegroundColor Cyan + foreach ($line in [string[]]$delivery.IntroText) { + Write-Host " $line" + } + } + if ($delivery.IntroFile) { + $introDest = Join-Path $dest ([IO.Path]::GetFileName([string]$delivery.IntroFile)) + if (Test-Path -LiteralPath $introDest) { + $hasIntro = $true + Write-Host '' + Write-Host "Introduction (from $([IO.Path]::GetFileName($introDest))):" -ForegroundColor Cyan + try { Write-Host (Get-Content -LiteralPath $introDest -Raw -ErrorAction Stop) } catch {} + } + } + if ($delivery.ImportantLinks) { + Write-Host '' + Write-Host 'Links:' -ForegroundColor Cyan + foreach ($l in $delivery.ImportantLinks) { + try { + $title = if ($l.Title) { $l.Title } elseif ($l.Name) { $l.Name } else { '' } + $url = $l.Url + if ($title -and $url) { + Write-Host " - $title" + Write-Host " $url" + } elseif ($url) { + Write-Host " - $url" + } elseif ($title) { + Write-Host " - $title" + } + } catch {} + } + } + } + } + + # Optionally open README in destination + if ($Open) { + try { + $readme = Get-ChildItem -LiteralPath $dest -Filter 'README*' -File -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($readme) { + Start-Process -FilePath $readme.FullName | Out-Null + } else { + # If README not found, open the destination folder + Start-Process -FilePath $dest | Out-Null + } + } catch { + Write-Verbose "Open failed: $($_.Exception.Message)" + } + } + } + } + end { + if ($resolvedTargets.Count -gt 0) { $resolvedTargets | Select-Object -Unique } + } +} diff --git a/Public/Invoke-DotNetReleaseBuild.ps1 b/Module/Public/Invoke-DotNetReleaseBuild.ps1 similarity index 94% rename from Public/Invoke-DotNetReleaseBuild.ps1 rename to Module/Public/Invoke-DotNetReleaseBuild.ps1 index bfdb68f0..4307f59f 100644 --- a/Public/Invoke-DotNetReleaseBuild.ps1 +++ b/Module/Public/Invoke-DotNetReleaseBuild.ps1 @@ -120,9 +120,9 @@ function Invoke-DotNetReleaseBuild { $null = New-Item -ItemType Directory -Path $releasePath -Force } - dotnet build $csproj.FullName --configuration Release + $buildOutput = & dotnet build $csproj.FullName --configuration Release 2>&1 if ($LASTEXITCODE -ne 0) { - $result.ErrorMessage = 'dotnet build failed.' + $result.ErrorMessage = "dotnet build failed. ExitCode=$LASTEXITCODE\n" + ($buildOutput | Out-String) return [PSCustomObject]$result } if ($CertificateThumbprint) { @@ -132,9 +132,9 @@ function Invoke-DotNetReleaseBuild { Compress-Archive -Path (Join-Path $releasePath '*') -DestinationPath $zipPath -Force # Pack the main project - dotnet pack $csproj.FullName --configuration Release --no-restore --no-build + $packOutput = & dotnet pack $csproj.FullName --configuration Release --no-restore --no-build 2>&1 if ($LASTEXITCODE -ne 0) { - $result.ErrorMessage = 'dotnet pack failed.' + $result.ErrorMessage = "dotnet pack failed. ExitCode=$LASTEXITCODE\n" + ($packOutput | Out-String) return [PSCustomObject]$result } @@ -143,9 +143,10 @@ function Invoke-DotNetReleaseBuild { Write-Verbose "Invoke-DotNetReleaseBuild - Packing $($dependencyProjects.Count) dependency projects" foreach ($depProj in $dependencyProjects) { Write-Verbose "Invoke-DotNetReleaseBuild - Packing dependency: $(Split-Path -Leaf $depProj)" - dotnet pack $depProj --configuration Release --no-restore --no-build + $depOut = & dotnet pack $depProj --configuration Release --no-restore --no-build 2>&1 if ($LASTEXITCODE -ne 0) { Write-Warning "Invoke-DotNetReleaseBuild - Failed to pack dependency: $(Split-Path -Leaf $depProj)" + if ($depOut) { Write-Verbose ($depOut | Out-String) } } } } diff --git a/Public/Invoke-ModuleBuild.ps1 b/Module/Public/Invoke-ModuleBuild.ps1 similarity index 94% rename from Public/Invoke-ModuleBuild.ps1 rename to Module/Public/Invoke-ModuleBuild.ps1 index cdef1b42..1f7cda28 100644 --- a/Public/Invoke-ModuleBuild.ps1 +++ b/Module/Public/Invoke-ModuleBuild.ps1 @@ -47,19 +47,23 @@ function Invoke-ModuleBuild { Include all files in the Artefacts from given folders. Default are 'Images', 'Resources', 'Templates', 'Bin', 'Lib', 'Data' folders. .PARAMETER IncludeCustomCode - Parameter description + Optional scriptblock executed during staging that can add custom files/folders + to the build. Use helper functions like Add-Directory/Copy-Item to place extra + content into the temporary module structure before merge/packaging. .PARAMETER IncludeToArray - Parameter description + Advanced hashtable form for includes. Supports keys matching IncludeRoot, + IncludePS1, IncludeAll etc. Prefer the dedicated parameters unless you need + to pass a single structured object. .PARAMETER LibrariesCore - Parameter description + Alternate relative path for .NET Core-targeted libraries folder. Default: 'Lib/Core'. .PARAMETER LibrariesDefault - Parameter description + Alternate relative path for classic .NET Framework-targeted libraries folder. Default: 'Lib/Default'. .PARAMETER LibrariesStandard - Parameter description + Alternate relative path for .NET Standard-targeted libraries folder. Default: 'Lib/Standard'. .PARAMETER ExitCode Exit code to be returned to the caller. If not provided, it will not exit the script, but finish gracefully. @@ -234,4 +238,4 @@ function Invoke-ModuleBuild { Exit 1 } } -} \ No newline at end of file +} diff --git a/Public/Invoke-ModuleTestSuite.ps1 b/Module/Public/Invoke-ModuleTestSuite.ps1 similarity index 100% rename from Public/Invoke-ModuleTestSuite.ps1 rename to Module/Public/Invoke-ModuleTestSuite.ps1 diff --git a/Public/New-ConfigurationArtefact.ps1 b/Module/Public/New-ConfigurationArtefact.ps1 similarity index 100% rename from Public/New-ConfigurationArtefact.ps1 rename to Module/Public/New-ConfigurationArtefact.ps1 diff --git a/Public/New-ConfigurationBuild.ps1 b/Module/Public/New-ConfigurationBuild.ps1 similarity index 86% rename from Public/New-ConfigurationBuild.ps1 rename to Module/Public/New-ConfigurationBuild.ps1 index 74d7fe90..788dbf8c 100644 --- a/Public/New-ConfigurationBuild.ps1 +++ b/Module/Public/New-ConfigurationBuild.ps1 @@ -13,31 +13,54 @@ Delete target module before build .PARAMETER MergeModuleOnBuild - Parameter description + Merge module on build. Combines Private/Public/Classes/Enums into a single PSM1 and prepares PSD1 accordingly. .PARAMETER MergeFunctionsFromApprovedModules - Parameter description + When merging, also include functions from ApprovedModules referenced by the module. .PARAMETER SignModule - Parameter description + Enables code-signing for the built module output. When enabled alone, only merged + scripts are signed (psm1/psd1/ps1) and Internals are excluded. Use the SignInclude* + switches to opt-in to additional content. + + .PARAMETER SignIncludeInternals + When signing is enabled, also sign scripts that reside under the Internals folder. + Default: disabled (Internals are skipped). + + .PARAMETER SignIncludeBinaries + When signing is enabled, include binary files (e.g., .dll, .cat) in signing. + Default: disabled. + + .PARAMETER SignIncludeExe + When signing is enabled, include .exe files. Default: disabled. + + .PARAMETER SignCustomInclude + Overrides the include patterns passed to the signer. If provided, this replaces + the defaults entirely. Example: '*.psm1','*.psd1','*.ps1','*.dll'. Use with + caution; it disables the default safe set. + + .PARAMETER SignExcludePaths + Additional path substrings to exclude from signing (relative matches). Example: + 'Examples','SomeFolder'. Internals are excluded by default unless + -SignIncludeInternals is specified. .PARAMETER DotSourceClasses - Parameter description + Keep classes in a separate dot-sourced file instead of merging them into the main PSM1. .PARAMETER DotSourceLibraries - Parameter description + Keep library-loading code in a separate dot-sourced file. .PARAMETER SeparateFileLibraries - Parameter description + Write library-loading code into a distinct file and reference it via ScriptsToProcess/DotSource. .PARAMETER RefreshPSD1Only - Parameter description + Only regenerate the manifest (PSD1) without rebuilding/merging other artifacts. .PARAMETER UseWildcardForFunctions - Parameter description + Export all functions/aliases via wildcard in PSD1. Useful for debugging non-merged builds. .PARAMETER LocalVersioning - Parameter description + Use local versioning (bump PSD1 version on each build without querying PSGallery). .PARAMETER DoNotAttemptToFixRelativePaths Configures module builder to not replace $PSScriptRoot\..\ with $PSScriptRoot\ @@ -47,22 +70,22 @@ Best practice is to use $MyInvocation.MyCommand.Module.ModuleBase or similar instead of relative paths. .PARAMETER CertificateThumbprint - Parameter description + Thumbprint of a code-signing certificate from the local cert store to sign module files. .PARAMETER CertificatePFXPath - Parameter description + Path to a PFX containing a code-signing certificate used for signing. .PARAMETER CertificatePFXBase64 - Parameter description + Base64 string of a PFX (e.g., provided via CI secrets) used for signing. .PARAMETER CertificatePFXPassword - Parameter description + Password for the PFX provided via -CertificatePFXPath or -CertificatePFXBase64. .PARAMETER NETConfiguration - Parameter description + Build configuration for .NET projects ('Release' or 'Debug'). .PARAMETER NETFramework - Parameter description + Target frameworks for .NET build (e.g., 'netstandard2.0','net6.0'). .PARAMETER NETProjectPath Path to the project that you want to build. This is useful if it's not in Sources folder directly within module directory @@ -165,6 +188,11 @@ [switch] $MergeModuleOnBuild, [switch] $MergeFunctionsFromApprovedModules, [switch] $SignModule, + [switch] $SignIncludeInternals, + [switch] $SignIncludeBinaries, + [switch] $SignIncludeExe, + [string[]] $SignCustomInclude, + [string[]] $SignExcludePaths, [switch] $DotSourceClasses, [switch] $DotSourceLibraries, [switch] $SeparateFileLibraries, @@ -240,6 +268,20 @@ } } } + if ($PSBoundParameters.ContainsKey('SignIncludeInternals') -or $PSBoundParameters.ContainsKey('SignIncludeBinaries') -or $PSBoundParameters.ContainsKey('SignIncludeExe') -or $PSBoundParameters.ContainsKey('SignCustomInclude') -or $PSBoundParameters.ContainsKey('SignExcludePaths')) { + [ordered] @{ + Type = 'Options' + Options = [ordered] @{ + Signing = [ordered] @{ + IncludeInternals = $SignIncludeInternals.IsPresent + IncludeBinaries = $SignIncludeBinaries.IsPresent + IncludeExe = $SignIncludeExe.IsPresent + Include = $SignCustomInclude + ExcludePaths = $SignExcludePaths + } + } + } + } if ($PSBoundParameters.ContainsKey('DotSourceClasses')) { # only when there are classes [ordered] @{ diff --git a/Module/Public/New-ConfigurationCommand.ps1 b/Module/Public/New-ConfigurationCommand.ps1 new file mode 100644 index 00000000..5d2493f1 --- /dev/null +++ b/Module/Public/New-ConfigurationCommand.ps1 @@ -0,0 +1,33 @@ +function New-ConfigurationCommand { + <# + .SYNOPSIS + Defines a command import configuration for the build pipeline. + + .DESCRIPTION + Creates a configuration object that specifies a module and one or more command names + to reference during the build process (for discovery, linking, or documentation). + + .PARAMETER ModuleName + Name of the module that contains the commands. + + .PARAMETER CommandName + One or more command names to reference from the module. + + .EXAMPLE + New-ConfigurationCommand -ModuleName 'PSSharedGoods' -CommandName 'Write-Text','Remove-EmptyValue' + #> + [CmdletBinding()] + param( + [string] $ModuleName, + [string[]] $CommandName + ) + + $Configuration = [ordered] @{ + Type = 'Command' + Configuration = [ordered] @{ + ModuleName = $ModuleName + CommandName = $CommandName + } + } + $Configuration +} diff --git a/Public/New-ConfigurationCompatibility.ps1 b/Module/Public/New-ConfigurationCompatibility.ps1 similarity index 100% rename from Public/New-ConfigurationCompatibility.ps1 rename to Module/Public/New-ConfigurationCompatibility.ps1 diff --git a/Module/Public/New-ConfigurationDelivery.ps1 b/Module/Public/New-ConfigurationDelivery.ps1 new file mode 100644 index 00000000..168502d4 --- /dev/null +++ b/Module/Public/New-ConfigurationDelivery.ps1 @@ -0,0 +1,174 @@ +function New-ConfigurationDelivery { + <# + .SYNOPSIS + Configures delivery metadata for bundling and installing internal docs/examples. + + .DESCRIPTION + Adds Delivery options to the PSPublishModule configuration so the build embeds + runtime metadata in the manifest (PrivateData.PSData.Delivery and PrivateData.PSData.Repository) + and so the Internals folder is easy to find post-install by helper cmdlets + such as Install-ModuleDocumentation. + + Typical usage is to call this in your Build\Manage-Module.ps1 alongside + New-ConfigurationInformation -IncludeAll 'Internals\' so that the Internals + directory is physically included in the shipped module and discoverable later. + + .PARAMETER Enable + Enables delivery metadata emission. If not specified, nothing is emitted. + + .PARAMETER InternalsPath + Relative path inside the module that contains internal deliverables + (e.g. 'Internals'). Defaults to 'Internals'. + + .PARAMETER IncludeRootReadme + Include module root README.* during installation (if present). + + .PARAMETER IncludeRootChangelog + Include module root CHANGELOG.* during installation (if present). + + .PARAMETER IncludeRootLicense + Include module root LICENSE.* during installation (if present). + + .PARAMETER ReadmeDestination + Where to bundle README.* within the built module. One of: Internals, Root, Both, None. Default: Internals. + + .PARAMETER ChangelogDestination + Where to bundle CHANGELOG.* within the built module. One of: Internals, Root, Both, None. Default: Internals. + + .PARAMETER LicenseDestination + Where to bundle LICENSE.* within the built module. One of: Internals, Root, Both, None. Default: Internals. + + .PARAMETER ImportantLinks + One or more key/value pairs that represent important links to display to the user, + for example @{ Title = 'Docs'; Url = 'https://...' }. + + .PARAMETER IntroText + Text lines shown to users after Install-ModuleDocumentation completes. Accepts a string array. + + .PARAMETER UpgradeText + Text lines with upgrade instructions shown when requested via Show-ModuleDocumentation -Upgrade. + + .PARAMETER IntroFile + Relative path (within the module root) to a Markdown/text file to use as the Intro content. + If provided, it is preferred over IntroText for display and is also copied by + Install-ModuleDocumentation. + + .PARAMETER UpgradeFile + Relative path (within the module root) to a Markdown/text file to use for Upgrade instructions. + If provided, it is preferred over UpgradeText for display and is also copied by + Install-ModuleDocumentation. + + .PARAMETER RepositoryPaths + One or more repository-relative paths (folders) from which to display remote documentation files + directly from the git hosting provider (GitHub/Azure DevOps). This enables tools such as + PSMaintenance to fetch and present docs straight from the repository when local copies are not + present or when explicitly requested. Requires PrivateData.PSData.ProjectUri to be set in the manifest. + + .PARAMETER RepositoryBranch + Optional branch name to use when fetching remote documentation. If omitted, providers fall back to + the repository default branch (e.g., main/master). + + .PARAMETER DocumentationOrder + Optional file-name order for Internals\Docs when rendering documentation. Provide names such as + 'Intro.md','HowTo.md','FAQ.md'; files not listed are appended alphabetically. + + .EXAMPLE + PS> New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -IncludeRootReadme -IncludeRootChangelog + Emits Options.Delivery and causes PrivateData.PSData.Delivery/Repository to be written in the manifest. + + .EXAMPLE + PS> New-ConfigurationInformation -IncludeAll 'Internals\' + PS> New-ConfigurationDelivery -Enable + Minimal configuration that bundles Internals and exposes it to the installer. + + .EXAMPLE + # Include Internals and configure Docs ordering + repo docs + New-ConfigurationInformation -IncludeAll 'Internals\' + New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -DocumentationOrder '01-Intro.md','02-HowTo.md','99-FAQ.md' -RepositoryPaths 'docs' -RepositoryBranch 'main' + # This causes: + # - Internals\Docs to be bundled and shown in the UI in the given order (remaining files alphabetically) + # - Repository Docs folder to be fetched/displayed when -PreferRepository is used, also respecting DocumentationOrder + + .EXAMPLE + # GitHub: configure remote docs + # 1) Set token once (Windows): setx PG_GITHUB_TOKEN "ghp_xxx" + # or call Set-ModuleDocumentation -GitHubToken 'ghp_xxx' + # 2) In your build script, indicate where docs live in the repo + New-ConfigurationDelivery -Enable -RepositoryPaths 'docs' -RepositoryBranch main + # Then on the viewing side: Show-ModuleDocumentation -Name EFAdminManager -PreferRepository + + .EXAMPLE + # Azure DevOps: configure remote docs + # URL form: https://dev.azure.com/{organization}/{project}/_git/{repository} + # PAT scope: Code (Read) + # 1) Set token once (Windows): setx PG_AZDO_PAT "your_pat" + # or call Set-ModuleDocumentation -AzureDevOpsPat 'your_pat' + # 2) In your build script, indicate repo docs path + New-ConfigurationDelivery -Enable -RepositoryPaths 'Docs/en-US' -RepositoryBranch main + # Then on the viewing side: Show-ModuleDocumentation -Name EFAdminManager -PreferRepository + + .EXAMPLE + # Mix Intro/Upgrade from files with ImportantLinks and include LICENSE in both root and Internals + New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -IntroFile 'Docs\\Intro.md' -UpgradeFile 'Docs\\Upgrade.md' -ImportantLinks @( + @{ Title = 'Home'; Url = 'https://contoso.example/docs' }, + @{ Title = 'Issues'; Url = 'https://contoso.example/issues' } + ) -IncludeRootLicense -LicenseDestination Both + + .EXAMPLE + # Multiple repository docs roots and custom order + New-ConfigurationDelivery -Enable -RepositoryPaths 'docs','guides' -RepositoryBranch main -DocumentationOrder '01-Intro.md','20-FAQ.md' + + .NOTES + This emits a Type 'Options' object under Options.Delivery so it works with the + existing New-PrepareStructure logic without further changes. + #> + [CmdletBinding()] + param( + [switch] $Enable, + [string] $InternalsPath = 'Internals', + [switch] $IncludeRootReadme, + [switch] $IncludeRootChangelog, + [switch] $IncludeRootLicense, + [ValidateSet('Internals','Root','Both','None')] + [string] $ReadmeDestination = 'Internals', + [ValidateSet('Internals','Root','Both','None')] + [string] $ChangelogDestination = 'Internals', + [ValidateSet('Internals','Root','Both','None')] + [string] $LicenseDestination = 'Internals', + [System.Collections.IDictionary[]] $ImportantLinks, + [string[]] $IntroText, + [string[]] $UpgradeText, + [string] $IntroFile, + [string] $UpgradeFile, + [string[]] $RepositoryPaths, + [string] $RepositoryBranch, + [string[]] $DocumentationOrder + ) + + if (-not $Enable) { return } + + $delivery = [ordered] @{ + Enable = $true + InternalsPath = $InternalsPath + IncludeRootReadme = $IncludeRootReadme.IsPresent + IncludeRootChangelog = $IncludeRootChangelog.IsPresent + ReadmeDestination = $ReadmeDestination + ChangelogDestination = $ChangelogDestination + LicenseDestination = $LicenseDestination + IncludeRootLicense = $IncludeRootLicense.IsPresent + ImportantLinks = $ImportantLinks + IntroText = $IntroText + UpgradeText = $UpgradeText + IntroFile = $IntroFile + UpgradeFile = $UpgradeFile + RepositoryPaths = $RepositoryPaths + RepositoryBranch = $RepositoryBranch + DocumentationOrder = $DocumentationOrder + Schema = '1.3' + } + + [ordered] @{ + Type = 'Options' + Options = [ordered] @{ Delivery = $delivery } + } +} diff --git a/Public/New-ConfigurationDocumentation.ps1 b/Module/Public/New-ConfigurationDocumentation.ps1 similarity index 100% rename from Public/New-ConfigurationDocumentation.ps1 rename to Module/Public/New-ConfigurationDocumentation.ps1 diff --git a/Module/Public/New-ConfigurationExecute.ps1 b/Module/Public/New-ConfigurationExecute.ps1 new file mode 100644 index 00000000..d6e50982 --- /dev/null +++ b/Module/Public/New-ConfigurationExecute.ps1 @@ -0,0 +1,16 @@ +function New-ConfigurationExecute { + <# + .SYNOPSIS + Reserved placeholder for future execution-time configuration. + + .DESCRIPTION + This cmdlet currently acts as a placeholder to keep backward compatibility with + older build scripts that may reference it. It returns nothing and performs no action. + + .EXAMPLE + New-ConfigurationExecute + Does nothing and returns no output. + #> + [CmdletBinding()] + param() +} diff --git a/Public/New-ConfigurationFileConsistency.ps1 b/Module/Public/New-ConfigurationFileConsistency.ps1 similarity index 100% rename from Public/New-ConfigurationFileConsistency.ps1 rename to Module/Public/New-ConfigurationFileConsistency.ps1 diff --git a/Public/New-ConfigurationFormat.ps1 b/Module/Public/New-ConfigurationFormat.ps1 similarity index 65% rename from Public/New-ConfigurationFormat.ps1 rename to Module/Public/New-ConfigurationFormat.ps1 index a2498023..9930bc38 100644 --- a/Public/New-ConfigurationFormat.ps1 +++ b/Module/Public/New-ConfigurationFormat.ps1 @@ -1,4 +1,114 @@ function New-ConfigurationFormat { + <# + .SYNOPSIS + Builds formatting options for code and manifest generation during the build. + + .DESCRIPTION + Produces a configuration object that controls how script and manifest files are formatted + during merge and in the default (non-merged) module. You can toggle specific PSScriptAnalyzer + rules, whitespace/indentation behavior, comment removal, and choose PSD1 output style. + + .PARAMETER ApplyTo + One or more targets to apply formatting to: OnMergePSM1, OnMergePSD1, DefaultPSM1, DefaultPSD1. + + .PARAMETER EnableFormatting + When set, enables formatting for the chosen ApplyTo targets even if no specific rule switches are provided. + + .PARAMETER Sort + Optional ordering hint for internal processing. Accepts None, Asc, or Desc. + + .PARAMETER RemoveComments + Remove comments in the formatted output. + + .PARAMETER RemoveEmptyLines + Remove empty lines while preserving readability. + + .PARAMETER RemoveAllEmptyLines + Remove all empty lines (more aggressive than RemoveEmptyLines). + + .PARAMETER RemoveCommentsInParamBlock + Remove comments within the param() block. + + .PARAMETER RemoveCommentsBeforeParamBlock + Remove comments that appear immediately before the param() block. + + .PARAMETER PlaceOpenBraceEnable + Enable PSPlaceOpenBrace rule and configure its behavior. + + .PARAMETER PlaceOpenBraceOnSameLine + For PSPlaceOpenBrace: place opening brace on the same line. + + .PARAMETER PlaceOpenBraceNewLineAfter + For PSPlaceOpenBrace: enforce a new line after the opening brace. + + .PARAMETER PlaceOpenBraceIgnoreOneLineBlock + For PSPlaceOpenBrace: ignore single-line blocks. + + .PARAMETER PlaceCloseBraceEnable + Enable PSPlaceCloseBrace rule and configure its behavior. + + .PARAMETER PlaceCloseBraceNewLineAfter + For PSPlaceCloseBrace: enforce a new line after the closing brace. + + .PARAMETER PlaceCloseBraceIgnoreOneLineBlock + For PSPlaceCloseBrace: ignore single-line blocks. + + .PARAMETER PlaceCloseBraceNoEmptyLineBefore + For PSPlaceCloseBrace: do not allow an empty line before a closing brace. + + .PARAMETER UseConsistentIndentationEnable + Enable PSUseConsistentIndentation rule and configure its behavior. + + .PARAMETER UseConsistentIndentationKind + Indentation style: 'space' or 'tab'. + + .PARAMETER UseConsistentIndentationPipelineIndentation + Pipeline indentation mode: IncreaseIndentationAfterEveryPipeline or NoIndentation. + + .PARAMETER UseConsistentIndentationIndentationSize + Number of spaces for indentation when Kind is 'space'. + + .PARAMETER UseConsistentWhitespaceEnable + Enable PSUseConsistentWhitespace rule and configure which elements to check. + + .PARAMETER UseConsistentWhitespaceCheckInnerBrace + For PSUseConsistentWhitespace: check inner brace spacing. + + .PARAMETER UseConsistentWhitespaceCheckOpenBrace + For PSUseConsistentWhitespace: check open brace spacing. + + .PARAMETER UseConsistentWhitespaceCheckOpenParen + For PSUseConsistentWhitespace: check open parenthesis spacing. + + .PARAMETER UseConsistentWhitespaceCheckOperator + For PSUseConsistentWhitespace: check operator spacing. + + .PARAMETER UseConsistentWhitespaceCheckPipe + For PSUseConsistentWhitespace: check pipeline operator spacing. + + .PARAMETER UseConsistentWhitespaceCheckSeparator + For PSUseConsistentWhitespace: check separator (comma) spacing. + + .PARAMETER AlignAssignmentStatementEnable + Enable PSAlignAssignmentStatement rule and optionally check hashtable alignment. + + .PARAMETER AlignAssignmentStatementCheckHashtable + For PSAlignAssignmentStatement: align hashtable assignments. + + .PARAMETER UseCorrectCasingEnable + Enable PSUseCorrectCasing rule. + + .PARAMETER PSD1Style + Style for generated manifests (PSD1) for the selected ApplyTo targets. 'Minimal' or 'Native'. + + .EXAMPLE + New-ConfigurationFormat -ApplyTo 'OnMergePSD1','DefaultPSD1' -PSD1Style 'Minimal' + Minimizes PSD1 output during merge and default builds. + + .EXAMPLE + New-ConfigurationFormat -ApplyTo 'OnMergePSM1' -EnableFormatting -UseConsistentIndentationEnable -UseConsistentIndentationKind space -UseConsistentIndentationIndentationSize 4 + Enables indentation and whitespace rules for merged PSM1. + #> [CmdletBinding()] param( [Parameter(Mandatory)] @@ -185,4 +295,4 @@ } # $Config = New-ConfigurationFormat -ApplyTo OnMergePSD1, DefaultPSD1 -PSD1Style Minimal -# $Config.Options \ No newline at end of file +# $Config.Options diff --git a/Public/New-ConfigurationImportModule.ps1 b/Module/Public/New-ConfigurationImportModule.ps1 similarity index 100% rename from Public/New-ConfigurationImportModule.ps1 rename to Module/Public/New-ConfigurationImportModule.ps1 diff --git a/Module/Public/New-ConfigurationInformation.ps1 b/Module/Public/New-ConfigurationInformation.ps1 new file mode 100644 index 00000000..e98b333d --- /dev/null +++ b/Module/Public/New-ConfigurationInformation.ps1 @@ -0,0 +1,81 @@ +function New-ConfigurationInformation { + <# + .SYNOPSIS + Describes what to include/exclude in the module build and how libraries are organized. + + .DESCRIPTION + Emits a configuration block with folder-level include/exclude rules and optional library + locations that the builder uses to stage content prior to merge/packaging. + + .PARAMETER FunctionsToExportFolder + Folder name containing public functions to export (e.g., 'Public'). + + .PARAMETER AliasesToExportFolder + Folder name containing public aliases to export (e.g., 'Public'). + + .PARAMETER ExcludeFromPackage + Paths or patterns to exclude from artefacts (e.g., 'Ignore','Docs','Examples'). + + .PARAMETER IncludeRoot + File patterns from the root to include (e.g., '*.psm1','*.psd1','License*'). + + .PARAMETER IncludePS1 + Folder names where PS1 files should be included (e.g., 'Private','Public','Enums','Classes'). + + .PARAMETER IncludeAll + Folder names to include entirely (e.g., 'Images','Resources','Templates','Bin','Lib','Data'). + + .PARAMETER IncludeCustomCode + Scriptblock executed during staging to add custom files/folders. + + .PARAMETER IncludeToArray + Advanced form to pass IncludeRoot/IncludePS1/IncludeAll as a single hashtable. + + .PARAMETER LibrariesCore + Relative path to libraries compiled for Core (default 'Lib/Core'). + + .PARAMETER LibrariesDefault + Relative path to libraries for classic .NET (default 'Lib/Default'). + + .PARAMETER LibrariesStandard + Relative path to libraries for .NET Standard (default 'Lib/Standard'). + + .EXAMPLE + New-ConfigurationInformation -IncludeAll 'Internals\' -IncludePS1 'Private','Public' -ExcludeFromPackage 'Ignore','Docs' + #> + [cmdletbinding()] + param( + [string] $FunctionsToExportFolder, + [string] $AliasesToExportFolder, + [string[]] $ExcludeFromPackage, + [string[]] $IncludeRoot, + [string[]] $IncludePS1, + [string[]] $IncludeAll, + [scriptblock] $IncludeCustomCode, + [System.Collections.IDictionary] $IncludeToArray, + [string] $LibrariesCore, + [string] $LibrariesDefault, + [string] $LibrariesStandard + ) + + $Configuration = [ordered] @{ + FunctionsToExportFolder = $FunctionsToExportFolder + AliasesToExportFolder = $AliasesToExportFolder + ExcludeFromPackage = $ExcludeFromPackage + IncludeRoot = $IncludeRoot + IncludePS1 = $IncludePS1 + IncludeAll = $IncludeAll + IncludeCustomCode = $IncludeCustomCode + IncludeToArray = $IncludeToArray + LibrariesCore = $LibrariesCore + LibrariesDefault = $LibrariesDefault + LibrariesStandard = $LibrariesStandard + } + Remove-EmptyValue -Hashtable $Configuration + + $Option = @{ + Type = 'Information' + Configuration = $Configuration + } + $Option +} diff --git a/Public/New-ConfigurationManifest.ps1 b/Module/Public/New-ConfigurationManifest.ps1 similarity index 91% rename from Public/New-ConfigurationManifest.ps1 rename to Module/Public/New-ConfigurationManifest.ps1 index 5a4f5653..0dc306e3 100644 --- a/Public/New-ConfigurationManifest.ps1 +++ b/Module/Public/New-ConfigurationManifest.ps1 @@ -45,6 +45,11 @@ .PARAMETER LicenseUri Specifies the URI for the module's license. + .PARAMETER RequireLicenseAcceptance + When set, indicates the module requires explicit user license acceptance (PowerShellGet). + If enabled, ensure a license file exists at the module root; the builder will + normalize any LICENSE/License.md to 'license.txt' in the final package. + .PARAMETER Prerelease Specifies the prerelease tag for the module. @@ -81,6 +86,7 @@ [string] $ProjectUri, [string] $DotNetFrameworkVersion, [string] $LicenseUri, + [switch] $RequireLicenseAcceptance, [alias('PrereleaseTag')][string] $Prerelease, [string[]] $FunctionsToExport, [string[]] $CmdletsToExport, @@ -102,6 +108,7 @@ ProjectUri = $ProjectUri DotNetFrameworkVersion = $DotNetFrameworkVersion LicenseUri = $LicenseUri + RequireLicenseAcceptance = $RequireLicenseAcceptance.IsPresent Prerelease = $Prerelease FunctionsToExport = $FunctionsToExport CmdletsToExport = $CmdletsToExport @@ -115,4 +122,4 @@ Configuration = $Manifest } $Option -} \ No newline at end of file +} diff --git a/Public/New-ConfigurationModule.ps1 b/Module/Public/New-ConfigurationModule.ps1 similarity index 100% rename from Public/New-ConfigurationModule.ps1 rename to Module/Public/New-ConfigurationModule.ps1 diff --git a/Public/New-ConfigurationModuleSkip.ps1 b/Module/Public/New-ConfigurationModuleSkip.ps1 similarity index 100% rename from Public/New-ConfigurationModuleSkip.ps1 rename to Module/Public/New-ConfigurationModuleSkip.ps1 diff --git a/Public/New-ConfigurationPlaceHolder.ps1 b/Module/Public/New-ConfigurationPlaceHolder.ps1 similarity index 100% rename from Public/New-ConfigurationPlaceHolder.ps1 rename to Module/Public/New-ConfigurationPlaceHolder.ps1 diff --git a/Public/New-ConfigurationPublish.ps1 b/Module/Public/New-ConfigurationPublish.ps1 similarity index 100% rename from Public/New-ConfigurationPublish.ps1 rename to Module/Public/New-ConfigurationPublish.ps1 diff --git a/Public/New-ConfigurationTest.ps1 b/Module/Public/New-ConfigurationTest.ps1 similarity index 61% rename from Public/New-ConfigurationTest.ps1 rename to Module/Public/New-ConfigurationTest.ps1 index 7febe231..8ddd6ab4 100644 --- a/Public/New-ConfigurationTest.ps1 +++ b/Module/Public/New-ConfigurationTest.ps1 @@ -1,4 +1,25 @@ function New-ConfigurationTest { + <# + .SYNOPSIS + Configures running Pester tests as part of the build. + + .DESCRIPTION + Emits test configuration that the builder uses to run tests. Currently, tests + are triggered AfterMerge. When -Enable is not provided, nothing is emitted. + + .PARAMETER TestsPath + Path to the folder containing Pester tests. + + .PARAMETER Enable + Enable test execution in the build. + + .PARAMETER Force + Force running tests even if they already ran or when caching would skip them. + + .EXAMPLE + New-ConfigurationTest -Enable -TestsPath 'Tests' -Force + Configures tests to run after merge from the 'Tests' folder. + #> [CmdletBinding()] param( #[Parameter(Mandatory)][ValidateSet('BeforeMerge', 'AfterMerge')][string[]] $When, @@ -28,4 +49,4 @@ $Configuration } } -} \ No newline at end of file +} diff --git a/Public/Publish-GitHubReleaseAsset.ps1 b/Module/Public/Publish-GitHubReleaseAsset.ps1 similarity index 100% rename from Public/Publish-GitHubReleaseAsset.ps1 rename to Module/Public/Publish-GitHubReleaseAsset.ps1 diff --git a/Public/Publish-NugetPackage.ps1 b/Module/Public/Publish-NugetPackage.ps1 similarity index 100% rename from Public/Publish-NugetPackage.ps1 rename to Module/Public/Publish-NugetPackage.ps1 diff --git a/Public/Register-Certificate.ps1 b/Module/Public/Register-Certificate.ps1 similarity index 57% rename from Public/Register-Certificate.ps1 rename to Module/Public/Register-Certificate.ps1 index 5e4a9fc4..7d6c456c 100644 --- a/Public/Register-Certificate.ps1 +++ b/Module/Public/Register-Certificate.ps1 @@ -1,4 +1,41 @@ function Register-Certificate { + <# + .SYNOPSIS + Signs files in a path using a code-signing certificate (Windows and PowerShell Core supported). + + .DESCRIPTION + Locates a code-signing certificate (by thumbprint from the Windows cert store or from a PFX) + and applies Authenticode signatures to matching files under -Path. + On Windows, uses Set-AuthenticodeSignature; on non-Windows, uses OpenAuthenticode module if available. + + .PARAMETER CertificatePFX + A PFX file to use for signing. Mutually exclusive with -LocalStore/-Thumbprint. + + .PARAMETER LocalStore + Certificate store to search ('LocalMachine' or 'CurrentUser') when using a certificate from the store. + + .PARAMETER Thumbprint + Certificate thumbprint to select a single certificate from the chosen -LocalStore. + + .PARAMETER Path + Root directory containing files to sign. + + .PARAMETER TimeStampServer + RFC3161 timestamp server URL. Default: http://timestamp.digicert.com + + .PARAMETER IncludeChain + Which portion of the chain to include in the signature: All, NotRoot, or Signer. Default: All. + + .PARAMETER Include + File patterns to include during signing. Defaults to scripts only: '*.ps1','*.psd1','*.psm1'. + You may pass additional patterns if needed (e.g., '*.dll'). + + .PARAMETER ExcludePath + One or more path substrings to exclude from signing. Useful for skipping folders like 'Internals' unless opted-in. + + .PARAMETER HashAlgorithm + Hash algorithm for the signature. Default: SHA256. + #> [cmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ParameterSetName = 'PFX')][string] $CertificatePFX, @@ -7,7 +44,8 @@ [Parameter(Mandatory)][string] $Path, [string] $TimeStampServer = 'http://timestamp.digicert.com', [ValidateSet('All', 'NotRoot', 'Signer')] [string] $IncludeChain = 'All', - [string[]] $Include = @('*.ps1', '*.psd1', '*.psm1', '*.dll', '*.cat'), + [string[]] $Include = @('*.ps1', '*.psd1', '*.psm1'), + [string[]] $ExcludePath, [ValidateSet('SHA1', 'SHA256', 'SHA384', 'SHA512')][string] $HashAlgorithm = 'SHA256' ) if ($PSBoundParameters.Keys -contains 'LocalStore') { @@ -65,9 +103,16 @@ } else { $IncludeOption = 'None' } - Get-ChildItem -Path $Path -Filter * -Include $Include -Recurse -ErrorAction SilentlyContinue | Where-Object { - ($_ | Get-OpenAuthenticodeSignature).Status -eq 'NotSigned' - } | Set-OpenAuthenticodeSignature -Certificate $Certificate -TimeStampServer $TimeStampServer -IncludeChain $IncludeOption -HashAlgorithm $HashAlgorithm + $items = Get-ChildItem -Path $Path -Filter * -Include $Include -Recurse -ErrorAction SilentlyContinue + if ($ExcludePath) { + $items = $items | Where-Object { + $full = $_.FullName + ($full -notlike '*\Internals\*' -and $full -notlike '*/Internals/*') -and ( + ($ExcludePath | ForEach-Object { $full -like ("*" + $_ + "*") }) -notcontains $true) + } + } + $items | Where-Object { ($_ | Get-OpenAuthenticodeSignature).Status -eq 'NotSigned' } | + Set-OpenAuthenticodeSignature -Certificate $Certificate -TimeStampServer $TimeStampServer -IncludeChain $IncludeOption -HashAlgorithm $HashAlgorithm } else { # This is for Windows, we need to use PKI module, it's usually installed by default @@ -76,10 +121,17 @@ Write-Warning -Message "Register-Certificate - Code signing commands not found. Skipping signing." return } - Get-ChildItem -Path $Path -Filter * -Include $Include -Recurse -ErrorAction SilentlyContinue | Where-Object { - ($_ | Get-AuthenticodeSignature).Status -eq 'NotSigned' - } | Set-AuthenticodeSignature -Certificate $Certificate -TimestampServer $TimeStampServer -IncludeChain $IncludeChain -HashAlgorithm $HashAlgorithm + $items = Get-ChildItem -Path $Path -Filter * -Include $Include -Recurse -ErrorAction SilentlyContinue + if ($ExcludePath) { + $items = $items | Where-Object { + $full = $_.FullName + ($full -notlike '*\Internals\*' -and $full -notlike '*/Internals/*') -and ( + ($ExcludePath | ForEach-Object { $full -like ("*" + $_ + "*") }) -notcontains $true) + } + } + $items | Where-Object { ($_ | Get-AuthenticodeSignature).Status -eq 'NotSigned' } | + Set-AuthenticodeSignature -Certificate $Certificate -TimestampServer $TimeStampServer -IncludeChain $IncludeChain -HashAlgorithm $HashAlgorithm } } } -} \ No newline at end of file +} diff --git a/Public/Remove-Comments.ps1 b/Module/Public/Remove-Comments.ps1 similarity index 100% rename from Public/Remove-Comments.ps1 rename to Module/Public/Remove-Comments.ps1 diff --git a/Public/Remove-ProjectFiles.ps1 b/Module/Public/Remove-ProjectFiles.ps1 similarity index 100% rename from Public/Remove-ProjectFiles.ps1 rename to Module/Public/Remove-ProjectFiles.ps1 diff --git a/Public/Send-GitHubRelease.ps1 b/Module/Public/Send-GitHubRelease.ps1 similarity index 100% rename from Public/Send-GitHubRelease.ps1 rename to Module/Public/Send-GitHubRelease.ps1 diff --git a/Public/Set-ProjectVersion.ps1 b/Module/Public/Set-ProjectVersion.ps1 similarity index 100% rename from Public/Set-ProjectVersion.ps1 rename to Module/Public/Set-ProjectVersion.ps1 diff --git a/Module/Public/Show-ProjectDocumentation.ps1 b/Module/Public/Show-ProjectDocumentation.ps1 new file mode 100644 index 00000000..5e5ac2e8 --- /dev/null +++ b/Module/Public/Show-ProjectDocumentation.ps1 @@ -0,0 +1,305 @@ +function Show-ProjectDocumentation { + <# + .SYNOPSIS + Shows README/CHANGELOG or a chosen document for a module, with a simple console view. + + .DESCRIPTION + Finds a module (by name or PSModuleInfo) and renders README/CHANGELOG from the module root + or from its Internals folder (as defined in PrivateData.PSData.Delivery). + You can also point directly to a docs folder via -DocsPath (e.g., output of Install-ModuleDocumentation). + + .PARAMETER Name + Module name to show documentation for. Accepts pipeline by value. + + .PARAMETER Module + A PSModuleInfo object (e.g., from Get-Module -ListAvailable) to operate on directly. + + .PARAMETER RequiredVersion + Specific version of the module to target. If omitted, selects the highest available. + + .PARAMETER DocsPath + A folder that contains documentation to display (e.g., the destination created by Install-ModuleDocumentation). + When provided, the cmdlet does not look up the module and shows docs from this folder. + + .PARAMETER Readme + Show README*. If both root and Internals copies exist, the root copy is preferred unless -PreferInternals is set. + + .PARAMETER Changelog + Show CHANGELOG*. If both root and Internals copies exist, the root copy is preferred unless -PreferInternals is set. + + .PARAMETER License + Show LICENSE. If multiple variants exist (LICENSE.md, LICENSE.txt), the resolver prefers a normalized 'license.txt' in + the chosen area (root vs Internals). + + .PARAMETER Intro + Show introduction text defined in PrivateData.PSData.Delivery.IntroText when available. If not defined, + falls back to README resolution (root vs Internals honoring -PreferInternals). + + .PARAMETER Upgrade + Show upgrade text defined in PrivateData.PSData.Delivery.UpgradeText when available. If not defined, + looks for an UPGRADE* file; otherwise throws. + + .PARAMETER All + Show Introduction, README, CHANGELOG and LICENSE in a standard order. You can still add + specific switches (e.g., -Changelog) and they will be included additively without duplication. + + .PARAMETER Links + Print ImportantLinks defined in PrivateData.PSData.Delivery after the selected documents. + + .PARAMETER File + Relative path to a specific file to display (relative to module root or Internals). If rooted, used as-is. + + .PARAMETER PreferInternals + Prefer the Internals copy of README/CHANGELOG when both exist. + + .PARAMETER List + List available README/CHANGELOG files found (root and Internals) instead of displaying content. + + .PARAMETER Raw + Output the raw file content (no styling). + + .PARAMETER Open + Open the resolved file in the system default viewer instead of rendering in the console. + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -Readme + + .EXAMPLE + Get-Module -ListAvailable EFAdminManager | Show-ProjectDocumentation -Changelog + + .EXAMPLE + Show-ProjectDocumentation -DocsPath 'C:\Docs\EFAdminManager\3.0.0' -Readme -Open + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -License + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -Intro + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -Upgrade + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -List + + .EXAMPLE + Show-ProjectDocumentation -Name EFAdminManager -All -Links + Displays Introduction, README, CHANGELOG, LICENSE and prints ImportantLinks. + + .EXAMPLE + # Prefer Internals copy of README/CHANGELOG when both root and Internals exist + Show-ProjectDocumentation -Name EFAdminManager -Readme -Changelog -PreferInternals + + .EXAMPLE + # Show a specific file from a copied docs folder + Show-ProjectDocumentation -DocsPath 'C:\\Docs\\EFAdminManager\\3.0.0' -File 'Internals\\Docs\\HowTo.md' + + .EXAMPLE + # Quick list of found README/CHANGELOG/License in root and Internals + Show-ProjectDocumentation -Name EFAdminManager -List | Format-Table -Auto + + .EXAMPLE + # Open the resolved README in the default viewer + Show-ProjectDocumentation -Name EFAdminManager -Readme -Open + #> + [CmdletBinding(DefaultParameterSetName='ByName')] + param( + [Parameter(ParameterSetName='ByName', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] + [Alias('ModuleName')] + [string] $Name, + [Parameter(ParameterSetName='ByModule', ValueFromPipeline=$true)] + [Alias('InputObject','ModuleInfo')] + [System.Management.Automation.PSModuleInfo] $Module, + [version] $RequiredVersion, + [Parameter(ParameterSetName='ByPath')] + [string] $DocsPath, + [switch] $Readme, + [switch] $Changelog, + [switch] $License, + [switch] $Intro, + [switch] $Upgrade, + [switch] $All, + [switch] $Links, + [string] $File, + [switch] $PreferInternals, + [switch] $List, + [switch] $Raw, + [switch] $Open + ) + + begin {} + process { + $rootBase = $null + $internalsBase = $null + $moduleName = $null + $moduleVersion = $null + + if ($PSCmdlet.ParameterSetName -eq 'ByPath') { + if (-not $DocsPath) { throw 'Specify -DocsPath for the ByPath parameter set.' } + if (-not (Test-Path -LiteralPath $DocsPath)) { throw "DocsPath '$DocsPath' not found." } + $rootBase = $DocsPath + $intCandidate = Join-Path $DocsPath 'Internals' + if (Test-Path -LiteralPath $intCandidate) { $internalsBase = $intCandidate } + } else { + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + if (-not $Name) { throw "Specify -Name or pipe a module via -Module." } + $candidates = Get-Module -ListAvailable -Name $Name + if (-not $candidates) { throw "Module '$Name' not found." } + if ($RequiredVersion) { + $Module = $candidates | Where-Object { $_.Version -eq $RequiredVersion } | Sort-Object Version -Descending | Select-Object -First 1 + if (-not $Module) { throw "Module '$Name' with version $RequiredVersion not found." } + } else { + $Module = $candidates | Sort-Object Version -Descending | Select-Object -First 1 + } + } elseif ($PSCmdlet.ParameterSetName -eq 'ByModule') { + if (-not $Module) { throw "Pipeline didn't pass a PSModuleInfo object. Use -Name or pipe Get-Module output." } + if ($RequiredVersion -and $Module.Version -ne $RequiredVersion) { + $resolved = Get-Module -ListAvailable -Name $Module.Name | Where-Object { $_.Version -eq $RequiredVersion } | Sort-Object Version -Descending | Select-Object -First 1 + if ($resolved) { $Module = $resolved } else { throw "Module '$($Module.Name)' with version $RequiredVersion not found." } + } + } + $rootBase = $Module.ModuleBase + $moduleName = $Module.Name + $moduleVersion = $Module.Version + + $manifestPath = Join-Path $rootBase ("{0}.psd1" -f $Module.Name) + $delivery = $null + if (Test-Path -LiteralPath $manifestPath) { + try { $manifest = Test-ModuleManifest -Path $manifestPath; $delivery = $manifest.PrivateData.PSData.Delivery } catch {} + } + $internalsRel = if ($delivery -and $delivery.InternalsPath) { [string]$delivery.InternalsPath } else { 'Internals' } + $intCandidate = Join-Path $rootBase $internalsRel + if (Test-Path -LiteralPath $intCandidate) { $internalsBase = $intCandidate } + } + + if ($List) { + $rows = @() + if ($rootBase) { + $rows += Get-ChildItem -LiteralPath $rootBase -Filter 'README*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Root' } } + $rows += Get-ChildItem -LiteralPath $rootBase -Filter 'CHANGELOG*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Root' } } + $rows += Get-ChildItem -LiteralPath $rootBase -Filter 'LICENSE*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Root' } } + } + if ($internalsBase) { + $rows += Get-ChildItem -LiteralPath $internalsBase -Filter 'README*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Internals' } } + $rows += Get-ChildItem -LiteralPath $internalsBase -Filter 'CHANGELOG*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Internals' } } + $rows += Get-ChildItem -LiteralPath $internalsBase -Filter 'LICENSE*' -File -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ Name=$_.Name; FullName=$_.FullName; Area='Internals' } } + } + if ($rows.Count -eq 0) { Write-Warning 'No README/CHANGELOG found.' } else { $rows } + return + } + # Build an additive list of targets to display in order + $targets = New-Object System.Collections.ArrayList + if ($File) { + $resolved = $null + if ([System.IO.Path]::IsPathRooted($File)) { + if (-not (Test-Path -LiteralPath $File)) { throw "File '$File' not found." } + $resolved = (Get-Item -LiteralPath $File).FullName + } else { + $try1 = if ($rootBase) { Join-Path $rootBase $File } + $try2 = if ($internalsBase) { Join-Path $internalsBase $File } + if ($try1 -and (Test-Path -LiteralPath $try1)) { $resolved = (Get-Item -LiteralPath $try1).FullName } + elseif ($try2 -and (Test-Path -LiteralPath $try2)) { $resolved = (Get-Item -LiteralPath $try2).FullName } + else { throw "File '$File' not found under root or Internals." } + } + [void]$targets.Add(@{ Kind='File'; Path=$resolved }) + } + if ($Intro) { [void]$targets.Add(@{ Kind='Intro' }) } + if ($All) { + if (-not $Intro) { [void]$targets.Add(@{ Kind='Intro' }) } + $f = Resolve-DocFile -Kind 'README' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f -and -not $Readme) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } + $f = Resolve-DocFile -Kind 'CHANGELOG' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f -and -not $Changelog) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } + $f = Resolve-DocFile -Kind 'LICENSE' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f -and -not $License) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } + } + if ($Readme) { + $f = Resolve-DocFile -Kind 'README' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } else { Write-Warning 'README not found.' } + } + if ($Changelog) { + $f = Resolve-DocFile -Kind 'CHANGELOG' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } else { Write-Warning 'CHANGELOG not found.' } + } + if ($License) { + $f = Resolve-DocFile -Kind 'LICENSE' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } else { Write-Warning 'LICENSE not found.' } + } + if ($Upgrade) { [void]$targets.Add(@{ Kind='Upgrade' }) } + + if ($targets.Count -eq 0) { + # Default when nothing specified: README else CHANGELOG + $f = Resolve-DocFile -Kind 'README' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if (-not $f) { $f = Resolve-DocFile -Kind 'CHANGELOG' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals } + if ($f) { [void]$targets.Add(@{ Kind='File'; Path=$f.FullName }) } else { throw 'No README or CHANGELOG found.' } + } + + # Handle -Open: only meaningful for single file target; otherwise open first file + if ($Open) { + $firstFile = ($targets | Where-Object { $_.Kind -eq 'File' } | Select-Object -First 1) + if ($firstFile) { Start-Process -FilePath $firstFile.Path | Out-Null; return } else { Start-Process -FilePath $rootBase | Out-Null; return } + } + + foreach ($t in $targets) { + if ($t.Kind -eq 'Intro') { + if ($manifest -and $manifest.PrivateData -and $manifest.PrivateData.PSData -and $manifest.PrivateData.PSData.Delivery -and $manifest.PrivateData.PSData.Delivery.IntroText) { + $title = if ($moduleName) { "$moduleName $moduleVersion - Introduction" } else { 'Introduction' } + Write-Heading -Text $title + foreach ($line in [string[]]$manifest.PrivateData.PSData.Delivery.IntroText) { Write-Host $line } + } else { + Write-Warning 'Introduction text not defined in delivery metadata.' + } + continue + } + if ($t.Kind -eq 'Upgrade') { + if ($manifest -and $manifest.PrivateData -and $manifest.PrivateData.PSData -and $manifest.PrivateData.PSData.Delivery -and $manifest.PrivateData.PSData.Delivery.UpgradeText) { + $title = if ($moduleName) { "$moduleName $moduleVersion - Upgrade" } else { 'Upgrade' } + Write-Heading -Text $title + foreach ($line in [string[]]$manifest.PrivateData.PSData.Delivery.UpgradeText) { Write-Host $line } + } else { + $f = Resolve-DocFile -Kind 'UPGRADE' -RootBase $rootBase -InternalsBase $internalsBase -PreferInternals:$PreferInternals + if ($f) { + $title = if ($moduleName) { "$moduleName $moduleVersion - $($f.Name)" } else { $f.Name } + Write-Heading -Text $title + try { $content = Get-Content -LiteralPath $f.FullName -Raw -ErrorAction Stop; Write-Host $content } catch { Write-Warning "Failed to read '$($f.FullName)': $($_.Exception.Message)" } + } else { + Write-Warning 'Upgrade instructions not defined and no UPGRADE file found.' + } + } + continue + } + # Kind = File + $target = $t.Path + if ($Raw) { + Get-Content -LiteralPath $target -Raw -ErrorAction Stop + } else { + $title = if ($moduleName) { "$moduleName $moduleVersion - $([IO.Path]::GetFileName($target))" } else { [IO.Path]::GetFileName($target) } + Write-Heading -Text $title + try { + $content = Get-Content -LiteralPath $target -Raw -ErrorAction Stop + Write-Host $content + } catch { + Write-Warning "Failed to read '$target': $($_.Exception.Message)" + } + } + Write-Host + } + if ($Links) { + $links = $manifest.PrivateData.PSData.Delivery.ImportantLinks + if ($links) { + Write-Heading -Text ((if ($moduleName) { "$moduleName $moduleVersion - Links" } else { 'Links' })) + foreach ($l in $links) { + $title = if ($l.Title) { $l.Title } elseif ($l.Name) { $l.Name } else { $null } + $url = $l.Url + if ($url) { + if ($title) { + Write-Host (" - {0}: {1}" -f $title, $url) + } else { + Write-Host (" - " + $url) + } + } + } + } + } + } +} diff --git a/Tests/Build-Module.Tests.ps1 b/Module/Tests/Build-Module.Tests.ps1 similarity index 100% rename from Tests/Build-Module.Tests.ps1 rename to Module/Tests/Build-Module.Tests.ps1 diff --git a/Tests/Convert-FileEncoding.Tests.ps1 b/Module/Tests/Convert-FileEncoding.Tests.ps1 similarity index 100% rename from Tests/Convert-FileEncoding.Tests.ps1 rename to Module/Tests/Convert-FileEncoding.Tests.ps1 diff --git a/Tests/Get-ModuleTestFailures.Tests.ps1 b/Module/Tests/Get-ModuleTestFailures.Tests.ps1 similarity index 100% rename from Tests/Get-ModuleTestFailures.Tests.ps1 rename to Module/Tests/Get-ModuleTestFailures.Tests.ps1 diff --git a/Tests/Get-PowerShellAssemblyMetadata.Tests.ps1 b/Module/Tests/Get-PowerShellAssemblyMetadata.Tests.ps1 similarity index 100% rename from Tests/Get-PowerShellAssemblyMetadata.Tests.ps1 rename to Module/Tests/Get-PowerShellAssemblyMetadata.Tests.ps1 diff --git a/Tests/Input/RemoveCommentsTests.ps1 b/Module/Tests/Input/RemoveCommentsTests.ps1 similarity index 100% rename from Tests/Input/RemoveCommentsTests.ps1 rename to Module/Tests/Input/RemoveCommentsTests.ps1 diff --git a/Tests/ModuleTestingFunctions.Tests.ps1 b/Module/Tests/ModuleTestingFunctions.Tests.ps1 similarity index 100% rename from Tests/ModuleTestingFunctions.Tests.ps1 rename to Module/Tests/ModuleTestingFunctions.Tests.ps1 diff --git a/Tests/Remove-Comments.Tests.ps1 b/Module/Tests/Remove-Comments.Tests.ps1 similarity index 100% rename from Tests/Remove-Comments.Tests.ps1 rename to Module/Tests/Remove-Comments.Tests.ps1 diff --git a/Tests/Step-Version.Tests.ps1 b/Module/Tests/Step-Version.Tests.ps1 similarity index 100% rename from Tests/Step-Version.Tests.ps1 rename to Module/Tests/Step-Version.Tests.ps1 diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 00000000..e18abf73 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Sources/PSPublishModule.sln b/PSPublishModule.sln similarity index 100% rename from Sources/PSPublishModule.sln rename to PSPublishModule.sln diff --git a/Sources/PSPublishModule/Initialize.cs b/PSPublishModule/Initialize.cs similarity index 81% rename from Sources/PSPublishModule/Initialize.cs rename to PSPublishModule/Initialize.cs index 814811c1..ca8a01c6 100644 --- a/Sources/PSPublishModule/Initialize.cs +++ b/PSPublishModule/Initialize.cs @@ -3,6 +3,4 @@ /// /// Dummy class to make the module visible to the module manager. /// -public class Initialize { - -} +public class Initialize { } diff --git a/Sources/PSPublishModule/OnImportAndRemove.cs b/PSPublishModule/OnImportAndRemove.cs similarity index 58% rename from Sources/PSPublishModule/OnImportAndRemove.cs rename to PSPublishModule/OnImportAndRemove.cs index 2d0de44e..b49f1c3f 100644 --- a/Sources/PSPublishModule/OnImportAndRemove.cs +++ b/PSPublishModule/OnImportAndRemove.cs @@ -3,37 +3,60 @@ using System.Management.Automation; using System.Reflection; +/// +/// Namespace for module import and removal handling. +/// public class OnModuleImportAndRemove : IModuleAssemblyInitializer, IModuleAssemblyCleanup { + /// + /// Handles module import event. + /// public void OnImport() { if (IsNetFramework()) { AppDomain.CurrentDomain.AssemblyResolve += MyResolveEventHandler; } } + /// + /// Handles module removal event. + /// + /// public void OnRemove(PSModuleInfo module) { if (IsNetFramework()) { AppDomain.CurrentDomain.AssemblyResolve -= MyResolveEventHandler; } } + /// + /// Custom assembly resolver to load assemblies from the module directory. + /// + /// + /// + /// private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) { //This code is used to resolve the assemblies //Console.WriteLine($"Resolving {args.Name}"); var directoryPath = Path.GetDirectoryName(typeof(OnModuleImportAndRemove).Assembly.Location); - var filesInDirectory = Directory.GetFiles(directoryPath); + if (directoryPath != null) { + var filesInDirectory = Directory.GetFiles(directoryPath); - foreach (var file in filesInDirectory) { - var fileName = Path.GetFileName(file); - var assemblyName = Path.GetFileNameWithoutExtension(file); + foreach (var file in filesInDirectory) { + var fileName = Path.GetFileName(file); + var assemblyName = Path.GetFileNameWithoutExtension(file); - if (args.Name.StartsWith(assemblyName)) { - //Console.WriteLine($"Loading {args.Name} assembly {fileName}"); - return Assembly.LoadFile(file); + if (args.Name.StartsWith(assemblyName)) { + //Console.WriteLine($"Loading {args.Name} assembly {fileName}"); + return Assembly.LoadFile(file); + } } } + return null; } + /// + /// Determines if the current runtime is .NET Framework. + /// + /// private bool IsNetFramework() { // Get the version of the CLR Version clrVersion = System.Environment.Version; @@ -41,10 +64,18 @@ private bool IsNetFramework() { return clrVersion.Major == 4; } + /// + /// Determines if the current runtime is .NET Core. + /// + /// private bool IsNetCore() { return System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase); } + /// + /// Determines if the current runtime is .NET 5 or higher. + /// + /// private bool IsNet5OrHigher() { return System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET 5", StringComparison.OrdinalIgnoreCase) || System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET 6", StringComparison.OrdinalIgnoreCase) || diff --git a/Sources/PSPublishModule/PSPublishModule.csproj b/PSPublishModule/PSPublishModule.csproj similarity index 100% rename from Sources/PSPublishModule/PSPublishModule.csproj rename to PSPublishModule/PSPublishModule.csproj diff --git a/Public/Initialize-PortableScript.ps1 b/Public/Initialize-PortableScript.ps1 deleted file mode 100644 index 33a42423..00000000 --- a/Public/Initialize-PortableScript.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -function Initialize-PortableScript { - [cmdletBinding()] - param( - [string] $FilePath, - [string] $OutputPath, - [Array] $ApprovedModules - ) - - if ($PSVersionTable.PSVersion.Major -gt 5) { - $Encoding = 'UTF8BOM' - } else { - $Encoding = 'UTF8' - } - - $Output = Get-MissingFunctions -FilePath $FilePath -SummaryWithCommands -ApprovedModules $ApprovedModules - $Script = Get-Content -LiteralPath $FilePath -Encoding UTF8 - $FinalScript = @( - $Output.Functions - $Script - ) - $FinalScript | Set-Content -LiteralPath $OutputPath -Encoding $Encoding - $Output -} \ No newline at end of file diff --git a/Public/New-ConfigurationCommand.ps1 b/Public/New-ConfigurationCommand.ps1 deleted file mode 100644 index e478aa51..00000000 --- a/Public/New-ConfigurationCommand.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -function New-ConfigurationCommand { - [CmdletBinding()] - param( - [string] $ModuleName, - [string[]] $CommandName - ) - - $Configuration = [ordered] @{ - Type = 'Command' - Configuration = [ordered] @{ - ModuleName = $ModuleName - CommandName = $CommandName - } - } - $Configuration -} \ No newline at end of file diff --git a/Public/New-ConfigurationExecute.ps1 b/Public/New-ConfigurationExecute.ps1 deleted file mode 100644 index e39223ff..00000000 --- a/Public/New-ConfigurationExecute.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -function New-ConfigurationExecute { - [CmdletBinding()] - param( - - ) -} \ No newline at end of file diff --git a/Public/New-ConfigurationInformation.ps1 b/Public/New-ConfigurationInformation.ps1 deleted file mode 100644 index 49c43e12..00000000 --- a/Public/New-ConfigurationInformation.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -function New-ConfigurationInformation { - [cmdletbinding()] - param( - [string] $FunctionsToExportFolder, - [string] $AliasesToExportFolder, - [string[]] $ExcludeFromPackage, - [string[]] $IncludeRoot, - [string[]] $IncludePS1, - [string[]] $IncludeAll, - [scriptblock] $IncludeCustomCode, - [System.Collections.IDictionary] $IncludeToArray, - [string] $LibrariesCore, - [string] $LibrariesDefault, - [string] $LibrariesStandard - ) - - $Configuration = [ordered] @{ - FunctionsToExportFolder = $FunctionsToExportFolder - AliasesToExportFolder = $AliasesToExportFolder - ExcludeFromPackage = $ExcludeFromPackage - IncludeRoot = $IncludeRoot - IncludePS1 = $IncludePS1 - IncludeAll = $IncludeAll - IncludeCustomCode = $IncludeCustomCode - IncludeToArray = $IncludeToArray - LibrariesCore = $LibrariesCore - LibrariesDefault = $LibrariesDefault - LibrariesStandard = $LibrariesStandard - } - Remove-EmptyValue -Hashtable $Configuration - - $Option = @{ - Type = 'Information' - Configuration = $Configuration - } - $Option -} \ No newline at end of file diff --git a/README.MD b/README.MD index 05d078be..2f691642 100644 --- a/README.MD +++ b/README.MD @@ -71,6 +71,32 @@ That's it. Whenever there's a new version you simply run the command and you can **The important thing** is if something works for you on production, keep using it till you test the new version on a test computer. I do changes that may not be big, but big enough that auto-update will break your code. For example, small rename to a parameter and your code stops working! Be responsible! +### Documentation - Local, GitHub, Azure DevOps + +PSPublishModule can bundle your module's Internals (Scripts, Docs, Binaries, Config) and root README/CHANGELOG/LICENSE. Use Install-ProjectDocumentation to copy them out for end‑users, and PSMaintenance to view docs with a rich UI (README + CHANGELOG + License + Docs tabs, dependencies graph, commands help). + +- Build-time bundling (in your module's Build script): + - `New-ConfigurationInformation -IncludeAll 'Internals\'` + - `New-ConfigurationDelivery -Enable -InternalsPath 'Internals' -IncludeRootReadme -IncludeRootChangelog -DocumentationOrder '01-Intro.md','02-HowTo.md'` + - Optional repository backfill (display docs directly from repo): + - GitHub: `New-ConfigurationDelivery -RepositoryPaths 'docs' -RepositoryBranch main` + - Azure DevOps: `New-ConfigurationDelivery -RepositoryPaths 'Docs/en-US' -RepositoryBranch main` + +- Copy docs for a module already installed: + - `Install-ProjectDocumentation -Name EFAdminManager -Path C:\Docs -Layout ModuleAndVersion` + - `Install-ProjectDocumentation -Name EFAdminManager -Path C:\Docs -Layout Direct` + - `Install-ProjectDocumentation -Name EFAdminManager -Path C:\Docs -OnExists Overwrite` + - `Install-ProjectDocumentation -Name EFAdminManager -Path C:\Docs -Layout Module -OnExists Merge -Force` + +- View docs (PSMaintenance): + - Local files: `Show-ModuleDocumentation -Name 'EFAdminManager' -Readme -Changelog` + - Prefer repository: `Show-ModuleDocumentation -Name 'EFAdminManager' -PreferRepository` + - Prefer Internals: `Show-ModuleDocumentation -Name 'EFAdminManager' -Readme -Changelog -PreferInternals` + - Specific file from copied docs: `Show-ModuleDocumentation -DocsPath 'C:\Docs\EFAdminManager\3.0.0' -File 'Internals\Docs\HowTo.md'` + - GitHub token (private repos): set once `setx PG_GITHUB_TOKEN "ghp_xxx"` or `Set-ModuleDocumentation -GitHubToken 'ghp_xxx'` + - Azure DevOps PAT (Code: Read): set once `setx PG_AZDO_PAT "your_pat"` or `Set-ModuleDocumentation -AzureDevOpsPat 'your_pat'` + - Repo URL format for AzDO: `https://dev.azure.com/{organization}/{project}/_git/{repository}` + ### Usage Introduced in **1.0.0** a new way to build PowerShell module based on DSL language. @@ -422,4 +448,4 @@ $Configuration = @{ } Build-Module -Configuration $Configuration -``` \ No newline at end of file +```