Skip to content

Modified Examples dir to provide a preview of PSake based module publ… #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Don't checkin this output dir
Release/

# Auto-generated test file
foo[1].ps1
56 changes: 47 additions & 9 deletions examples/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// A task runner that invokes Pester to run all Pester tests under the
// current workspace folder.

// NOTE: This Pester task runner requires an updated version of Pester (>=3.4.0)
// NOTE: This Test task runner requires an updated version of Pester (>=3.4.0)
// in order for the problemMatcher to find failed test information (message, line, file).
// If you don't have that version, you can update Pester from the PSGallery like so:
// If you don't have that version, you can update Pester from the PowerShell Gallery
// with this command:
//
// PS C:\> Update-Module Pester
//
Expand All @@ -14,14 +15,19 @@
// PS C:\> Install-Module Pester -Scope CurrentUser -Force
//

// NOTE: The Clean, Build and Publish tasks require PSake. PSake can be installed
// from the PowerShell Gallery with this command:
//
// PS C:\> Install-Module PSake -Scope CurrentUser -Force
//

// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process

{
"version": "0.1.0",

Expand All @@ -34,17 +40,49 @@
// Show the output window always
"showOutput": "always",

"args": [
"-NoProfile", "-ExecutionPolicy", "Bypass",
"Write-Host 'Invoking Pester...'; Invoke-Pester -PesterOption @{IncludeVSCodeMarker=$true};",
"Invoke-Command { Write-Host \"Completed all tasks in task runner: $($args[0])\" } -args"
],
"args": [
"-NoProfile", "-ExecutionPolicy", "Bypass"
],

// Associate with test task runner
"tasks": [
{
"taskName": "Pester",
"taskName": "Clean",
"suppressTaskName": true,
"showOutput": "always",
"args": [
"Write-Host 'Invoking PSake...'; Invoke-PSake build.ps1 -taskList Clean;",
"Invoke-Command { Write-Host 'Completed Clean task in task runner.' }"
]
},
{
"taskName": "Build",
"suppressTaskName": true,
"isBuildCommand": true,
"showOutput": "always",
"args": [
"Write-Host 'Invoking PSake...'; Invoke-PSake build.ps1 -taskList Build;",
"Invoke-Command { Write-Host 'Completed Build task in task runner.' }"
]
},
{
"taskName": "Publish",
"suppressTaskName": true,
"showOutput": "always",
"args": [
"Write-Host 'Invoking PSake...'; Invoke-PSake build.ps1 -taskList Publish;",
"Invoke-Command { Write-Host 'Completed Publish task in task runner.' }"
]
},
{
"taskName": "Test",
"suppressTaskName": true,
"isTestCommand": true,
"showOutput": "always",
"args": [
"Write-Host 'Invoking Pester...'; Invoke-Pester -PesterOption @{IncludeVSCodeMarker=$true};",
"Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
],
"problemMatcher": [
{
"owner": "powershell",
Expand Down
227 changes: 227 additions & 0 deletions examples/Build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
##############################################################################
# PREVIEW VERSION OF PSAKE SCRIPT FOR MODULE BUILD & PUBLISH TO THE PSGALLERY
##############################################################################
#
# We are hoping to add support for publishing modules to the PowerShell gallery
# and private repositories in a future release of this extension. This is an
# early look at the approach we are considering which is to supply a
# PSake-based script that will:
#
# 1. Create a directory from which to publish your module.
# 2. Copy the appropriate module files to that directory excluding items like
# the .vscode directory, Pester tests, etc. These are configurable in Build.ps1.
# 3. Verify all existing Pester tests pass.
# 4. Publish the module to the desired repository (defaulting to the PSGallery).
#
# Requirements: PSake. If you don't have this module installed use the following
# command to install it:
#
# PS C:\> Install-Module PSake -Scope CurrentUser
#
##############################################################################
# This is a PSake script that supports the following tasks:
# clean, build, test and publish. The default task is build.
#
# The publish task uses the Publish-Module command to publish
# to either the PowerShell Gallery (the default) or you can change
# the $Repository property to the name of an alternate repository.
#
# The test task invokes Pester to run any Pester tests in your
# workspace folder. Name your test scripts <TestName>.Tests.ps1
# and Pester will find and run the tests contained in the files.
#
# You can run this build script directly using the invoke-psake
# command which will execute the build task. This task "builds"
# a temporary folder from which the module can be published.
#
# PS C:\> invoke-psake build.ps1
#
# You can run your Pester tests (if any) by running the following command.
#
# PS C:\> invoke-psake build.ps1 -taskList test
#
# You can execute the publish task with the following command. Note that
# the publish task will run the test task first. The Pester tests must pass
# before the publish task will run. The first time you run the publish
# command, you will be prompted to enter your PowerShell Gallery NuGetApiKey.
# After entering the key, it is encrypted and stored so you will not have to
# enter it again.
#
# PS C:\> invoke-psake build.ps1 -taskList publish
#
# You can verify the stored and encrypted NuGetApiKey by running the following
# command. This will display your NuGetApiKey in plain text!
#
# PS C:\> invoke-psake build.ps1 -taskList showKey
#
# You can store a new NuGetApiKey with this command. You can leave off
# the -properties parameter and you'll be prompted for the key.
#
# PS C:\> invoke-psake build.ps1 -taskList storeKey -properties @{NuGetApiKey='test123'}
#

###############################################################################
# Customize these properties for your module.
###############################################################################
Properties {
# The name of your module should match the basename of the PSD1 file.
$ModuleName = (Get-Item $PSScriptRoot\*.psd1)[0].BaseName

# Path to the release notes file. Set to $null if the release notes reside in the manifest file.
$ReleaseNotesPath = "$PSScriptRoot\ReleaseNotes.md"

# The directory used to publish the module from. If you are using Git, the
# $PublishDir should be ignored if it is under the workspace directory.
$PublishDir = "$PSScriptRoot\Release\$ModuleName"

# The following items will not be copied to the $PublishDir.
# Add items that should not be published with the module.
$Exclude = @(
'Release',
'Tests',
'.git*',
'.vscode',
# The next three files are unique to this examples dir.
'DebugTest.ps1',
'Stop*.ps1',
'Readme.md',
(Split-Path $PSCommandPath -Leaf)
)

# Name of the repository you wish to publish to. Default repo is the PSGallery.
$PublishRepository = $null

# Your NuGet API key for the PSGallery. Leave it as $null and the first time
# you publish you will be prompted to enter your API key. The build will
# store the key encrypted in a file, so that on subsequent publishes you
# will no longer be prompted for the API key.
$NuGetApiKey = $null
$EncryptedApiKeyPath = "$env:LOCALAPPDATA\vscode-powershell\NuGetApiKey.clixml"
}

###############################################################################
# Customize these tasks for performing operations before and/or after publish.
###############################################################################
Task PrePublish {
}

Task PostPublish {
}

###############################################################################
# Core task implementations - this possibly "could" ship as part of the
# vscode-powershell extension and then get dot sourced into this file.
###############################################################################
Task default -depends Build

Task Publish -depends Test, PrePublish, PublishImpl, PostPublish {
}

Task PublishImpl -depends Test -requiredVariables PublishDir, EncryptedApiKeyPath {
$NuGetApiKey = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath

$publishParams = @{
Path = $PublishDir
NuGetApiKey = $NuGetApiKey
}

if ($PublishRepository) {
$publishParams['Repository'] = $PublishRepository
}

# Consider not using -ReleaseNotes parameter when Update-ModuleManifest has been fixed.
if ($ReleaseNotesPath) {
$publishParams['ReleaseNotes'] = @(Get-Content $ReleaseNotesPath)
}

"Calling Publish-Module..."
Publish-Module @publishParams -WhatIf
}

Task Test -depends Build {
Import-Module Pester
Invoke-Pester $PSScriptRoot
}

Task Build -depends Clean -requiredVariables PublishDir, Exclude, ModuleName {
Copy-Item $PSScriptRoot\* -Destination $PublishDir -Recurse -Exclude $Exclude

# Get contents of the ReleaseNotes file and update the copied module manifest file
# with the release notes.
# DO NOT USE UNTIL UPDATE-MODULEMANIFEST IS FIXED - HORRIBLY BROKEN RIGHT NOW.
# if ($ReleaseNotesPath) {
# $releaseNotes = @(Get-Content $ReleaseNotesPath)
# Update-ModuleManifest -Path $PublishDir\${ModuleName}.psd1 -ReleaseNotes $releaseNotes
# }
}

Task Clean -depends Init -requiredVariables PublishDir {
# Sanity check the dir we are about to "clean". If $PublishDir were to
# inadvertently get set to $null, the Remove-Item commmand removes the
# contents of \*. That's a bad day. Ask me how I know? :-(
if ($PublishDir.Contains($PSScriptRoot)) {
Remove-Item $PublishDir\* -Recurse -Force
}
}

Task Init -requiredVariables PublishDir {
if (!(Test-Path $PublishDir)) {
$null = New-Item $PublishDir -ItemType Directory
}
}

Task StoreKey -requiredVariables EncryptedApiKeyPath {
if (Test-Path $EncryptedApiKeyPath) {
Remove-Item $EncryptedApiKeyPath
}

$null = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath
"The NuGetApiKey has been stored in $EncryptedApiKeyPath"
}

Task ShowKey -requiredVariables EncryptedApiKeyPath {
$NuGetApiKey = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath
"The stored NuGetApiKey is: $NuGetApiKey"
}

Task ? -description 'Lists the available tasks' {
"Available tasks:"
$psake.context.Peek().tasks.Keys | Sort
}

###############################################################################
# Helper functions
###############################################################################
function Get-NuGetApiKey($NuGetApiKey, $EncryptedApiKeyPath) {
$storedKey = $null
if (!$NuGetApiKey) {
if (Test-Path $EncryptedApiKeyPath) {
$storedKey = Import-Clixml $EncryptedApiKeyPath | ConvertTo-SecureString
$cred = New-Object -TypeName PSCredential -ArgumentList 'kh',$storedKey
$NuGetApiKey = $cred.GetNetworkCredential().Password
Write-Verbose "Retrieved encrypted NuGetApiKey from $EncryptedApiKeyPath"
}
else {
$cred = Get-Credential -Message "Enter your NuGet API Key in the password field (or nothing, this isn't used yet in the preview)" -UserName "user"
$apiKeySS = $cred.Password
$NuGetApiKey = $cred.GetNetworkCredential().Password
}
}

if (!$storedKey) {
# Store encrypted NuGet API key to use for future invocations
if (!$apiKeySS) {
$apiKeySS = ConvertTo-SecureString -String $NuGetApiKey -AsPlainText -Force
}

$parentDir = Split-Path $EncryptedApiKeyPath -Parent
if (!(Test-Path -Path $parentDir)) {
$null = New-Item -Path $parentDir -ItemType Directory
}

$apiKeySS | ConvertFrom-SecureString | Export-Clixml $EncryptedApiKeyPath
Write-Verbose "Stored encrypted NuGetApiKey to $EncryptedApiKeyPath"
}

$NuGetApiKey
}
Binary file modified examples/DebugTest.ps1
Binary file not shown.
23 changes: 18 additions & 5 deletions examples/PathProcessingNoWildcards.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
<#
.SYNOPSIS
Demonstrates how to write a command that works with paths that do
not allow wildards but must exist.
.DESCRIPTION
This command does not require a LiteralPath parameter because the
Path parameter can handle paths that use wildcard characters. That's
because this command does not "resolve" the supplied path.
.EXAMPLE
C:\PS> Import-FileNoWildcard -Path ..\..\Tests\foo[1].txt -WhatIf
This example shows how the Path parameter can handle a path that happens
to use the wildcard chars "[" and "]".
#>
function Import-FileNoWildcard {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
Expand All @@ -13,10 +26,10 @@ function Import-FileNoWildcard {
[string[]]
$Path
)

begin {
}

process {
# Modify [CmdletBinding()] to [CmdletBinding(SupportsShouldProcess=$true)]
$paths = @()
Expand All @@ -28,19 +41,19 @@ function Import-FileNoWildcard {
$psCmdlet.WriteError($errRecord)
continue
}

# Resolve any relative paths
$paths += $psCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($aPath)
}

foreach ($aPath in $paths) {
if ($pscmdlet.ShouldProcess($aPath, 'Operation')) {
# Process each path
$aPath
}
}
}

end {
}
}
Loading