From fca3b39b2e4791a299525dc6cd123cb2ac3e5bd6 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Fri, 17 Feb 2023 13:26:03 -0800 Subject: [PATCH] Initial commit. --- .github/CODEOWNERS | 4 + .gitignore | 7 + CHANGELOG.md | 0 LICENSE.txt | 201 ++++++++++++++++++ NOTICE.txt | 5 + README.md | 26 +++ TODO.md | 31 +++ Tests/Import-W3CLogs.Tests.ps1 | 46 ++++ Tests/Initialize-Test.ps1 | 60 ++++++ Tests/W3CLogs.Tests.ps1 | 85 ++++++++ .../W3CLogsTestHelper/W3CLogsTestHelper.psm1 | 0 W3CLogs/Functions/Use-CallerPreference.ps1 | 107 ++++++++++ W3CLogs/W3CLogs.psd1 | 130 +++++++++++ W3CLogs/W3CLogs.psm1 | 35 +++ W3CLogs/en-US/about_W3CLogs.help.txt | 8 + appveyor.yml | 67 ++++++ build.ps1 | 158 ++++++++++++++ init.ps1 | 21 ++ prism.json | 4 + prism.lock.json | 4 + reset.ps1 | 17 ++ whiskey.yml | 95 +++++++++ 22 files changed, 1111 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE.txt create mode 100644 NOTICE.txt create mode 100644 README.md create mode 100644 TODO.md create mode 100644 Tests/Import-W3CLogs.Tests.ps1 create mode 100644 Tests/Initialize-Test.ps1 create mode 100644 Tests/W3CLogs.Tests.ps1 create mode 100644 Tests/W3CLogsTestHelper/W3CLogsTestHelper.psm1 create mode 100644 W3CLogs/Functions/Use-CallerPreference.ps1 create mode 100644 W3CLogs/W3CLogs.psd1 create mode 100644 W3CLogs/W3CLogs.psm1 create mode 100644 W3CLogs/en-US/about_W3CLogs.help.txt create mode 100644 appveyor.yml create mode 100644 build.ps1 create mode 100644 init.ps1 create mode 100644 prism.json create mode 100644 prism.lock.json create mode 100644 reset.ps1 create mode 100644 whiskey.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..eafc3bb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# These owners will be the default owners for everything in +# the repo. The owners will be requested for review when +# someone opens a pull request. +* @webmd-health-services/devops \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b368a6e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/.output +/PSModules +/.vscode +/W3CLogs/CHANGELOG.md +/W3CLogs/LICENSE.txt +/W3CLogs/NOTICE.txt +/W3CLogs/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..7c7610a --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,5 @@ +W3CLogs + +Copyright 2023 WebMD Health Services + +This product includes software developed at WebMD Health Services (https://www.webmdhealthservices.com/). diff --git a/README.md b/README.md new file mode 100644 index 0000000..342e6b5 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Overview + +The "W3CLogs" module... + +# System Requirements + +* Windows PowerShell 5.1 and .NET 4.6.1+ +* PowerShell Core 6+ + +# Installing + +To install globally: + +```powershell +Install-Module -Name 'W3CLogs' +Import-Module -Name 'W3CLogs' +``` + +To install privately: + +```powershell +Save-Module -Name 'W3CLogs' -Path '.' +Import-Module -Name '.\W3CLogs' +``` + +# Commands diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..19dd0cd --- /dev/null +++ b/TODO.md @@ -0,0 +1,31 @@ +# Using This Template + +Click the "Use this template" button above. Clone the new repository. Run the `.\Initialize-Repository.ps1` script. +Pass the name of the module to the `ModuleName` parameter. The script will: + +* Rename this file to TODO.md (there are additional steps to take afterward) +* Puts the default README.md file in place. +* Rename every file that has `W3CLogs` in its name, replacing `W3CLogs` with the module name. +* Replaces `W3CLogs` in every file with the module name. +* Installs and enables [Whiskey](https://github.com/webmd-health-services/Whiskey/wiki). +* Removes this script. +* If Git is installed, adds all the changes, and amends the initial commit with them so all traces of the template are + removed. + +# Manual Steps + +Things you'll still need to do after creating your repository: + +* Turn on branch protections. +* Create "develop" branch. +* Create a build in AppVeyor. +* Create a feature branch. +* Commit and push your new branch. A build should run in AppVeyor and finish successfully after a minute or so. The +default build will run using: + * Windows PowerShell 5.1/.NET 4.6.2 + * Windows PowerShell 5.1/.NET 4.8 + * PowerShell 6.2 on Windows + * PowerShell 7.1 on Windows + * PowerShell 7.2 on Windows + * PowerShell 7.1 on macOS + * PowerShell 7.2 on Ubuntu \ No newline at end of file diff --git a/Tests/Import-W3CLogs.Tests.ps1 b/Tests/Import-W3CLogs.Tests.ps1 new file mode 100644 index 0000000..0594afd --- /dev/null +++ b/Tests/Import-W3CLogs.Tests.ps1 @@ -0,0 +1,46 @@ + +#Requires -Version 5.1 +Set-StrictMode -Version 'Latest' + +BeforeAll { + & (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-Test.ps1' -Resolve) + + function GivenModuleLoaded + { + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\W3CLogs\W3CLogs.psd1' -Resolve) + Get-Module -Name 'W3CLogs' | Add-Member -MemberType NoteProperty -Name 'NotReloaded' -Value $true + } + + function GivenModuleNotLoaded + { + Remove-Module -Name 'W3CLogs' -Force -ErrorAction Ignore + } + + function ThenModuleLoaded + { + $module = Get-Module -Name 'W3CLogs' + $module | Should -Not -BeNullOrEmpty + $module | Get-Member -Name 'NotReloaded' | Should -BeNullOrEmpty + } + + function WhenImporting + { + $script:importedAt = Get-Date + Start-Sleep -Milliseconds 1 + & (Join-Path -Path $PSScriptRoot -ChildPath '..\W3CLogs\Import-W3CLogs.ps1' -Resolve) + } +} + +Describe 'Import-W3CLogs' { + It 'should import the module' { + GivenModuleNotLoaded + WhenImporting + ThenModuleLoaded + } + + It 'should re-import the module' { + GivenModuleLoaded + WhenImporting + ThenModuleLoaded + } +} diff --git a/Tests/Initialize-Test.ps1 b/Tests/Initialize-Test.ps1 new file mode 100644 index 0000000..de4e39e --- /dev/null +++ b/Tests/Initialize-Test.ps1 @@ -0,0 +1,60 @@ +<# +.SYNOPSIS +Gets things ready for your tests to run. + +.DESCRIPTION +The `Initialize-Test.ps1` script gets your tests ready to run by: + +* Importing the module you're testing. +* Importing your test helper module. +* Importing any other module dependencies your tests have. + +Execute this script as the first thing in each of your test fixtures: + + #Requires -Version 5.1 + Set-StrictMode -Version 'Latest' + + & (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-Test.ps1' -Resolve) +#> +[CmdletBinding()] +param( +) + +$originalVerbosePref = $Global:VerbosePreference +$originalWhatIfPref = $Global:WhatIfPreference + +$Global:VerbosePreference = $VerbosePreference = 'SilentlyContinue' +$Global:WhatIfPreference = $WhatIfPreference = $false + +try +{ + $modules = [ordered]@{ + 'W3CLogs' = '..\W3CLogs'; + 'MODULE_NAMETestHelper' = 'MODULE_NAMETestHelper'; + } + foreach( $moduleName in $modules.Keys ) + { + $module = Get-Module -Name $moduleName + $modulePath = Join-Path $PSScriptRoot -ChildPath $modules[$moduleName] -Resolve + if( $module ) + { + # Don't constantly reload modules on the build server. + if( (Test-Path -Path 'env:WHS_CI') -and $module.Path.StartsWith($modulePath) ) + { + continue + } + + Write-Verbose -Message ('Removing module "{0}".' -f $moduleName) + Remove-Module -Name $moduleName -Force + } + + Write-Verbose -Message ('Importing module "{0}" from "{1}".' -f $moduleName,$modulePath) + Import-Module -Name $modulePath + } +} +finally +{ + $Global:VerbosePreference = $originalVerbosePref + $Global:WhatIfPreference = $originalWhatIfPref +} + diff --git a/Tests/W3CLogs.Tests.ps1 b/Tests/W3CLogs.Tests.ps1 new file mode 100644 index 0000000..2903cc2 --- /dev/null +++ b/Tests/W3CLogs.Tests.ps1 @@ -0,0 +1,85 @@ +# This test fixture is for testing that the module meets coding standards that are testable. + +#Requires -Version 5.1 +Set-StrictMode -Version 'Latest' + +BeforeAll { + & (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-Test.ps1' -Resolve) + + function GivenModuleImported + { + # Don't do anything since Initialize-Test.ps1 imports the module. + } + + function ThenUseApprovedVerbs + { + param( + ) + + $verbs = + Get-Command -Module 'W3CLogs'| + Where-Object { $_ -isnot [Management.Automation.AliasInfo] } | + Select-Object -ExpandProperty Verb | + Select-Object -Unique + if( $verbs ) + { + $approvedVerbs = Get-Verb | Select-Object -ExpandProperty Verb + $verbs | Should -BeIn $approvedVerbs + } + } + + function ThenHelpTopic + { + param( + [Parameter(Mandatory, Position=0)] + [String] $Named, + + [Parameter(Mandatory)] + [switch] $Exists, + + [switch] $HasSynopsis, + + [switch] $HasDescription, + + [switch] $HasExamples + ) + + $help = Get-Help -Name $Named -Full + $help | Should -Not -BeNullOrEmpty + + if( $HasSynopsis ) + { + $help.Synopsis | Should -Not -BeNullOrEmpty + } + + if( $HasDescription ) + { + $help.Description | Should -Not -BeNullOrEmpty + } + + if( $HasExamples ) + { + $help.Examples | Should -Not -BeNullOrEmpty + } + } +} + +Describe 'W3CLogs' { + It 'should have about help topic' { + GivenModuleImported + ThenHelpTopic 'about_MODULE_NAME' -Exists + } + + It 'should only use approved verbs' { + GivenModuleImported + ThenUseApprovedVerbs + } + + It 'should have a help topic for each command' { + GivenModuleImported + foreach( $cmd in (Get-Command -Module 'W3CLogs' -CommandType Function,Cmdlet,Filter)) + { + ThenHelpTopic $cmd.Name -Exists -HasSynopsis -HasDescription -HasExamples + } + } +} \ No newline at end of file diff --git a/Tests/W3CLogsTestHelper/W3CLogsTestHelper.psm1 b/Tests/W3CLogsTestHelper/W3CLogsTestHelper.psm1 new file mode 100644 index 0000000..e69de29 diff --git a/W3CLogs/Functions/Use-CallerPreference.ps1 b/W3CLogs/Functions/Use-CallerPreference.ps1 new file mode 100644 index 0000000..5d6820a --- /dev/null +++ b/W3CLogs/Functions/Use-CallerPreference.ps1 @@ -0,0 +1,107 @@ + +function Use-CallerPreference +{ + <# + .SYNOPSIS + Sets the PowerShell preference variables in a module's function based on the callers preferences. + + .DESCRIPTION + Script module functions do not automatically inherit their caller's variables, including preferences set by common + parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't + get passed into any function that belongs to a module. + + When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the + function's caller: + + * ErrorAction + * Debug + * Confirm + * InformationAction + * Verbose + * WarningAction + * WhatIf + + This function should be used in a module's function to grab the caller's preference variables so the caller doesn't + have to explicitly pass common parameters to the module function. + + This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d). + + There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that + causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add + explicit `-ErrorAction $ErrorActionPreference` to every `Write-Error` call. Please vote up this issue so it can get + fixed. + + .LINK + about_Preference_Variables + + .LINK + about_CommonParameters + + .LINK + https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d + + .LINK + http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/ + + .EXAMPLE + Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + + Demonstrates how to set the caller's common parameter preference variables in a module function. + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + #[Management.Automation.PSScriptCmdlet] + # The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` + # attribute. + $Cmdlet, + + [Parameter(Mandatory)] + # The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the + # `[CmdletBinding()]` attribute. + # + # Used to set variables in its callers' scope, even if that caller is in a different script module. + [Management.Automation.SessionState]$SessionState + ) + + Set-StrictMode -Version 'Latest' + + # List of preference variables taken from the about_Preference_Variables and their common parameter name (taken + # from about_CommonParameters). + $commonPreferences = @{ + 'ErrorActionPreference' = 'ErrorAction'; + 'DebugPreference' = 'Debug'; + 'ConfirmPreference' = 'Confirm'; + 'InformationPreference' = 'InformationAction'; + 'VerbosePreference' = 'Verbose'; + 'WarningPreference' = 'WarningAction'; + 'WhatIfPreference' = 'WhatIf'; + } + + foreach( $prefName in $commonPreferences.Keys ) + { + $parameterName = $commonPreferences[$prefName] + + # Don't do anything if the parameter was passed in. + if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) ) + { + continue + } + + $variable = $Cmdlet.SessionState.PSVariable.Get($prefName) + # Don't do anything if caller didn't use a common parameter. + if( -not $variable ) + { + continue + } + + if( $SessionState -eq $ExecutionContext.SessionState ) + { + Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false + } + else + { + $SessionState.PSVariable.Set($variable.Name, $variable.Value) + } + } +} \ No newline at end of file diff --git a/W3CLogs/W3CLogs.psd1 b/W3CLogs/W3CLogs.psd1 new file mode 100644 index 0000000..1e197dc --- /dev/null +++ b/W3CLogs/W3CLogs.psd1 @@ -0,0 +1,130 @@ +# Copyright WebMD Health Services +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'W3CLogs.psm1' + + # Version number of this module. + ModuleVersion = '0.0.0' + + # ID used to uniquely identify this module + GUID = '' + + # Author of this module + Author = 'WebMD Health Services' + + # Company or vendor of this module + CompanyName = 'WebMD Health Services' + + # If you want to support .NET Core, add 'Core' to this list. + CompatiblePSEditions = @( 'Desktop', 'Core' ) + + # Copyright statement for this module + Copyright = '(c) WebMD Health Services.' + + # Description of the functionality provided by this module + Description = '' + + # Minimum version of the Windows PowerShell engine required by this module + PowerShellVersion = '5.1' + + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module + # CLRVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @( ) + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @( ) + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module. Only list public function here. + FunctionsToExport = @( + ) + + # Cmdlets to export from this module. By default, you get a script module, so there are no cmdlets. + # CmdletsToExport = @() + + # Variables to export from this module. Don't export variables except in RARE instances. + VariablesToExport = @() + + # Aliases to export from this module. Don't create/export aliases. It can pollute your user's sessions. + AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @( 'Desktop', 'Core' ) + + # A URL to the license for this module. + LicenseUri = 'http://www.apache.org/licenses/LICENSE-2.0' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/webmd-health-services/W3CLogs' + + # A URL to an icon representing this module. + # IconUri = '' + + Prerelease = '' + + # ReleaseNotes of this module + ReleaseNotes = @' +'@ + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' +} diff --git a/W3CLogs/W3CLogs.psm1 b/W3CLogs/W3CLogs.psm1 new file mode 100644 index 0000000..cff7de7 --- /dev/null +++ b/W3CLogs/W3CLogs.psm1 @@ -0,0 +1,35 @@ +# Copyright WebMD Health Services +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License + +#Requires -Version 5.1 +Set-StrictMode -Version 'Latest' + +# Functions should use $moduleRoot as the relative root from which to find +# things. A published module has its function appended to this file, while a +# module in development has its functions in the Functions directory. +$moduleRoot = $PSScriptRoot + +# Store each of your module's functions in its own file in the Functions +# directory. On the build server, your module's functions will be appended to +# this file, so only dot-source files that exist on the file system. This allows +# developers to work on a module without having to build it first. Grab all the +# functions that are in their own files. +$functionsPath = Join-Path -Path $moduleRoot -ChildPath 'Functions\*.ps1' +if( (Test-Path -Path $functionsPath) ) +{ + foreach( $functionPath in (Get-Item $functionsPath) ) + { + . $functionPath.FullName + } +} diff --git a/W3CLogs/en-US/about_W3CLogs.help.txt b/W3CLogs/en-US/about_W3CLogs.help.txt new file mode 100644 index 0000000..35effa8 --- /dev/null +++ b/W3CLogs/en-US/about_W3CLogs.help.txt @@ -0,0 +1,8 @@ +TOPIC + about_MODULE_NAME + +SHORT DESCRIPTION + W3CLogs is a PowerShell module for... + +LONG DESCRIPTION + The W3CLogs PowerShell module... diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..45c0f28 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,67 @@ +version: 0.0.0+{build} + +skip_tags: true + +skip_branch_with_pr: true + +build: + verbosity: minimal + +test: off + +environment: + WHISKEY_DISABLE_ERROR_FORMAT: True + matrix: + - job_name: PowerShell 7.2 on Windows + job_group: pwsh + appveyor_build_worker_image: Visual Studio 2022 + + - job_name: PowerShell 7.1 on macOS + job_group: pwsh + appveyor_build_worker_image: macOS + + - job_name: Windows PowerShell 5.1/.NET 4.6.2 + job_group: ps + appveyor_build_worker_image: Visual Studio 2013 + + - job_name: Windows PowerShell 5.1/.NET 4.8 + job_group: ps + appveyor_build_worker_image: Visual Studio 2019 + + - job_name: PowerShell 6.2 on Windows + job_group: pwsh + appveyor_build_worker_image: Visual Studio 2015 + + - job_name: PowerShell 7.2 on Ubuntu + job_group: pwsh + appveyor_build_worker_image: Ubuntu + + - job_name: PowerShell 7.1 on Windows + job_group: pwsh + appveyor_build_worker_image: Visual Studio 2019 + + +artifacts: +- path: .output\* + + +for: +# Build in Windows PowerShell +- matrix: + only: + - job_group: ps + build_script: + - ps: | + $ProgressPreference = 'SilentlyContinue' + iwr https://raw.githubusercontent.com/webmd-health-services/Prism/main/Scripts/init.ps1 | iex | Format-Table + .\build.ps1 + +# Build in PowerShell +- matrix: + only: + - job_group: pwsh + build_script: + - pwsh: | + $ProgressPreference = 'SilentlyContinue' + iwr https://raw.githubusercontent.com/webmd-health-services/Prism/main/Scripts/init.ps1 | iex | Format-Table + ./build.ps1 diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..a6b6869 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,158 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS +Starts a Whiskey build. + +.DESCRIPTION +The `build.ps1` script starts a Whiskey build in the script's root directory. It will first download the latest `0.*` version of Whiskey from Whiskey's GitHub [Releases](https://github.com/webmd-health-services/Whiskey/releases) and place it into a `PSModules/Whiskey` directory. The script will look for a `whiskey.yml` file in the same directory as itself. If one doesn't exit, it will create a new starter `whiskey.yml` file with empty `Build` and `Publish` pipelines. Finally, `Invoke-WhiskeyBuild` is called to run the build tasks specified in the `whiskey.yml`. + +To download all the tools that are required for a build, use the `-Initialize` switch. + +To cleanup downloaded build tools and artifacts created from previous builds, use the `-Clean` switch. + +.EXAMPLE +./build.ps1 + +Starts a Whiskey build. + +.EXAMPLE +./build.ps1 -Clean + +Demonstrates how to use Whiskey to clean up any downloaded build tools and previously built artifacts. + +.EXAMPLE +./build.ps1 -Initialize + +Demonstrates how to initialize the build root with any tools that are required by tasks in the `whiskey.yml` file. +#> +[CmdletBinding(DefaultParameterSetName='Build')] +param( + [Parameter(Mandatory,ParameterSetName='Clean')] + # Runs the build in clean mode, which removes any files, tools, packages created by previous builds. + [switch]$Clean, + + [Parameter(Mandatory,ParameterSetName='Initialize')] + # Initializes the repository. + [switch]$Initialize +) + +#Requires -Version 5.1 +$ErrorActionPreference = 'Stop' + +Set-StrictMode -Version Latest + +# Set to a specific version to use a specific version of Whiskey. +$whiskeyVersion = '0.*' +$allowPrerelease = $false + +$psModulesRoot = Join-Path -Path $PSScriptRoot -ChildPath 'PSModules' +$whiskeyModuleRoot = Join-Path -Path $PSScriptRoot -ChildPath 'PSModules\Whiskey' + +if( -not (Test-Path -Path $whiskeyModuleRoot -PathType Container) ) +{ + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 + $release = + Invoke-RestMethod -Uri 'https://api.github.com/repos/webmd-health-services/Whiskey/releases' | + ForEach-Object { $_ } | + Where-Object { $_.name -like $whiskeyVersion } | + Where-Object { + if( $allowPrerelease ) + { + return $true + } + [Version]::TryParse($_.name,[ref]$null) + } | + Sort-Object -Property 'created_at' -Descending | + Select-Object -First 1 + + if( -not $release ) + { + Write-Error -Message ('Whiskey version "{0}" not found.' -f $whiskeyVersion) -ErrorAction Stop + return + } + + $zipUri = + $release.assets | + ForEach-Object { $_ } | + Where-Object { $_.name -like 'Whiskey*.zip' } | + Select-Object -ExpandProperty 'browser_download_url' + + if( -not $zipUri ) + { + Write-Error -Message ('URI to Whiskey ZIP file does not exist.') -ErrorAction Stop + } + + Write-Verbose -Message ('Found Whiskey {0}.' -f $release.name) + + if( -not (Test-Path -Path $psModulesRoot -PathType Container) ) + { + New-Item -Path $psModulesRoot -ItemType 'Directory' | Out-Null + } + $zipFilePath = Join-Path -Path $psModulesRoot -ChildPath 'Whiskey.zip' + & { + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -UseBasicParsing -Uri $zipUri -OutFile $zipFilePath + } + + # Whiskey.zip uses Windows directory separator which extracts strangely on Linux. So, we have + # to extract each entry by hand. + Add-Type -AssemblyName 'System.IO.Compression.FileSystem' + $zipFile = [IO.Compression.ZipFile]::OpenRead($zipFilePath) + try + { + foreach( $entry in $zipFile.Entries ) + { + $destinationPath = Join-Path -Path $whiskeyModuleRoot -ChildPath $entry.FullName + $destinationDirectory = $destinationPath | Split-Path + if( -not (Test-Path -Path $destinationDirectory -PathType Container) ) + { + New-Item -Path $destinationDirectory -ItemType 'Directory' | Out-Null + } + Write-Debug -Message ('{0} -> {1}' -f $entry.FullName,$destinationPath) + [IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $destinationPath, $true) + } + } + finally + { + $zipFile.Dispose() + } + + # Remove any prerelease information. + $moduleDirName = $release.name -replace '-.*$','' + Rename-Item -Path (Join-Path -Path $whiskeyModuleRoot -ChildPath 'Whiskey') -NewName $moduleDirName + + Remove-Item -Path $zipFilePath +} + +& { + $VerbosePreference = 'SilentlyContinue' + Import-Module -Name $whiskeyModuleRoot -Force +} + +$configPath = Join-Path -Path $PSScriptRoot -ChildPath 'whiskey.yml' +if( -not (Test-Path -Path $configPath -PathType 'Leaf') ) +{ + @' +Build: +- Version: + Version: 0.0.0 + +Publish: + +'@ | Set-Content -Path $configPath +} + +$optionalArgs = @{ } +if( $Clean ) +{ + $optionalArgs['Clean'] = $true +} + +if( $Initialize ) +{ + $optionalArgs['Initialize'] = $true +} + +$context = New-WhiskeyContext -Environment 'Dev' -ConfigurationPath $configPath +Invoke-WhiskeyBuild -Context $context @optionalArgs diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 0000000..cb59b11 --- /dev/null +++ b/init.ps1 @@ -0,0 +1,21 @@ +<# +.SYNOPSIS +Gets your computer ready to develop the W3CLogs module. + +.DESCRIPTION +The init.ps1 script makes the configuraion changes necessary to get your computer ready to develop for the +W3CLogs module. It: + + +.EXAMPLE +.\init.ps1 + +Demonstrates how to call this script. +#> +[CmdletBinding()] +param( +) + +Set-StrictMode -Version 'Latest' +$ErrorActionPreference = 'Stop' +$InformationPreference = 'Continue' diff --git a/prism.json b/prism.json new file mode 100644 index 0000000..394db36 --- /dev/null +++ b/prism.json @@ -0,0 +1,4 @@ +{ + "PSModules": [ + ] +} \ No newline at end of file diff --git a/prism.lock.json b/prism.lock.json new file mode 100644 index 0000000..394db36 --- /dev/null +++ b/prism.lock.json @@ -0,0 +1,4 @@ +{ + "PSModules": [ + ] +} \ No newline at end of file diff --git a/reset.ps1 b/reset.ps1 new file mode 100644 index 0000000..9d1b7fa --- /dev/null +++ b/reset.ps1 @@ -0,0 +1,17 @@ +<# +.SYNOPSIS +Undoes the configuration changes made by the init.ps1 script. + +.DESCRIPTION +The reset.ps1 script undoes the configuration changes made by the init.ps1 script. It: + +.EXAMPLE +.\reset.ps1 + +Demonstrates how to call this script. +#> +[CmdletBinding()] +param( +) + +Set-StrictMode -Version 'Latest' diff --git a/whiskey.yml b/whiskey.yml new file mode 100644 index 0000000..254297e --- /dev/null +++ b/whiskey.yml @@ -0,0 +1,95 @@ + +Build: +- PowerShell: + ExceptDuring: Clean + ScriptBlock: prism install | Format-Table -Auto + +- Version: + Path: W3CLogs\W3CLogs.psd1 + Prerelease: + - "*/*": alpha$(WHISKEY_BUILD_NUMBER) + - develop: rc$(WHISKEY_BUILD_NUMBER) + +# Update the AppVeyor build/version number. +- Exec: + OnlyBy: BuildServer + Path: appveyor + Argument: [ UpdateBuild, -Version, "$(WHISKEY_SEMVER2)+$(WHISKEY_BUILD_NUMBER)" ] + +# Dot-sourcing files is expensive. Move all functions into .psm1 file to improve import speed. Do this before testing +# to ensure the module still works. +- MergeFile: + OnlyBy: BuildServer + # Builds run twice on some serves. Only run this step if the module hasn't been merged yet. + IfExists: W3CLogs\Functions\*.ps1 + Path: + - W3CLogs\Functions\*.ps1 + DestinationPath: W3CLogs\W3CLogs.psm1 + DeleteSourceFiles: true + TextSeparator: "$(NewLine)$(NewLine)" + +- CopyFile: + Path: + - LICENSE.txt + - NOTICE.txt + - README.md + - CHANGELOG.md + DestinationDirectory: Carbon + +- PowerShell: + ExceptDuring: Clean + Path: init.ps1 + +- PowerShell: + OnlyDuring: Clean + Path: reset.ps1 + +# Build runs twice on some servers, so delete any ZIP file created by another build. +- Delete: + Path: .output\*.zip + +- CopyFile: + Path: + - CHANGELOG.md + - README.md + - LICENSE + - NOTICE + DestinationDirectory: W3CLogs + +- Zip: + ArchivePath: .output\W3CLogs-$(WHISKEY_SEMVER2).zip + Path: + - W3CLogs + Exclude: + - "*.pdb" + - "*.orig" + +- Exec: + OnlyBy: BuildServer + Path: appveyor + Argument: [ 'PushArtifact', '.output/W3CLogs-$(WHISKEY_SEMVER2).zip', '-DeploymentName', 'GitHub' ] + + +- PublishPowerShellModule: + Path: W3CLogs + +- Exec: + OnlyBy: BuildServer + Path: appveyor + Argument: [ + 'PushArtifact', + '.output/W3CLogs.$(WHISKEY_SEMVER2_NO_BUILD_METADATA).nupkg', + '-DeploymentName', + 'PowerShellGallery' + ] + +- Pester: + Configuration: + Run: + Path: Tests\*.Tests.ps1 + Exit: true + Throw: true + TestResult: + Enabled: true + OutputPath: .output\pester.xml + TestSuiteName: Template-PSModule-OSS-Apache2.0 \ No newline at end of file