From b16400c08030d7d349ee4b96a324c5dc1ad88389 Mon Sep 17 00:00:00 2001 From: "Joel Sallow (/u/ta11ow)" <32407840+vexx32@users.noreply.github.com> Date: Sat, 21 Mar 2020 16:50:56 -0400 Subject: [PATCH] :recycle: Refactor AboutCmdletVerbs (#378) * :recycle: Refactor AboutCmdletVerbs * :rocket: Adjust build name * :recycle: Address review comments * :recycle: Address review comments --- .../Introduction/AboutCmdletVerbs.Koans.ps1 | 266 ++++++++++++------ azure-pipelines.yml | 6 +- 2 files changed, 189 insertions(+), 83 deletions(-) diff --git a/PSKoans/Koans/Introduction/AboutCmdletVerbs.Koans.ps1 b/PSKoans/Koans/Introduction/AboutCmdletVerbs.Koans.ps1 index 80ca08048..a8726aa1c 100644 --- a/PSKoans/Koans/Introduction/AboutCmdletVerbs.Koans.ps1 +++ b/PSKoans/Koans/Introduction/AboutCmdletVerbs.Koans.ps1 @@ -4,39 +4,53 @@ param() <# Cmdlet Verbs - The fundamental building block of PowerShell are cmdlets and functions. + The fundamental building block of PowerShell are cmdlets and functions, both + of which are named according to a Verb-Noun syntax by convention. - We'll cover functions later, but cmdlets are made up of the following syntax: + You can see the list of PowerShell's recommended / approved verbs by calling + Get-Verb in your PowerShell console, or going to the following docs page: + https://docs.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands - Verb-Noun + Each command should use a verb appropriate to the action it's taking, and a + noun that succinctly and clearly describes what it's acting upon. - With the verb being an action, and the noun representing the target of the command. - - In this topic, we'll cover the 5 basic verbs which'll see you through the majority of your - PowerShell needs. But PowerShell has more than just 5 predefined verbs! You can see them - all by running the following cmdlet: - - Get-Verb + In this topic, we'll cover a few of the most common verbs which you'll see + most frequently. #> Describe "Basic Verbs" { + BeforeAll { + # We'll be using this path later on. + $FilePath = "$env:TMP/YOUR_PATH.txt" + + if (Test-Path $FilePath) { + Remove-Item -Path $FilePath + } + } + Context "Get" { <# Cmdlets with the Get verb are used for retrieving data. - So for example "Get-Process" will retrieve all the processes running on - your current machine. + So for example "Get-Process" will retrieve all the processes running + on your current machine. #> It 'is for commands that retrieve data' { <# - Using the Get-Command cmdlet, which retrieves all available commands, - find 5 commands with the Get verb. + Using the Get-Command cmdlet, which retrieves all available + commands, find 5 commands with the Get verb. - Replace each ____ with the name of a Get-* command. + Fill in each blank with the name of a different Get-* command. #> - $Answers = "____", "____", "____", "____", "____" + $Answers = @( + "____" + "____" + "____" + "____" + "____" + ) $Answers | Should -BeIn (Get-Command -Verb Get).Name $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required" @@ -47,15 +61,8 @@ Describe "Basic Verbs" { <# Cmdlets with the New verb are used to create data. - So for example 'New-GUID' will create a new GUID, or 'New-LocalUser' will create a local - user on your machine. - - Before continuing with this exercise, try using the following code to create a file: - - $Path = "YOUR PATH.txt" - New-Item -Path $Path -ItemType file - - This will create a new text file, in the location you specify. + So for example 'New-Guid' will create a new GUID, or 'New-TimeSpan' + will create a new [timespan] object with the specified parameters. #> It 'is for commands that create data' { @@ -64,34 +71,60 @@ Describe "Basic Verbs" { Replace each ____ with the name of a New-* command. #> - $Answers = "____", "____", "____", "____", "____" + $Answers = @( + "____" + "____" + "____" + "____" + "____" + ) $Answers | Should -BeIn (Get-Command -Verb New).Name $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required" } - } - Context "Add" { - <# - Cmdlets with the Add verb append data to an existing object or data source. + It 'can create a New-Item' { + <# + Let's try creating a file! + + Use New-Item to create a new text file, in the location + specified with the $FilePath variable, which is defined above. - If you followed the example in the 'new' test, you can use Add-Content to add some - text to your newly created text file: + The necessary parameters are already filled in for you here. In + this case, the file we're creating is simply empty. You could + also specify a -Value parameter with some text to put in the + newly-created file. - $Path = "YOUR PATH.txt" - Add-Content -Path $Path -Value "Sgt. Bash is the best house robot because... fire." + Take some time to experiment with New-Item in your console if + you'd like to see what it can do! Start with: - Before continuing, run this command several times. See what happens; is it the - result you expected? + Get-Command New-Item -Syntax + Get-Help New-Item -Examples + #> + + $File = ____ -Path $FilePath -ItemType File + + # All "file" objects are of this type. + $File | Should -BeOfType [System.IO.FileInfo] + + # An empty file has a "length" of zero. + $File.Length | Should -Be 0 + } + } - You'll see that several lines of text were added to the file. This cmdlet only appends - information, it does not overwrite. + Context "Add" { + <# + Cmdlets with the Add verb append data to an existing object or data + source. - Basically, if it doesn't exist then a cmdlet with the add verb can probably be used - to make it so. + Essentially, if the target doesn't exist then a cmdlet with the Add + verb will typically create it. If it does exist, the cmdlet will + add data to it, if data can be added without overwriting the + original data. - A common example one might see working with Office 365 is calendar permissions. - If you want to grant permissions to somebody who doesn't have any, you use "Add-MailboxFolderPermission". + A common example one might see working with Office 365 is calendar + permissions. If you want to grant permissions to somebody who + doesn't have any, you use "Add-MailboxFolderPermission". #> It 'is for commands that append data' { @@ -105,33 +138,62 @@ Describe "Basic Verbs" { $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required" } - } - Context "Set" { - <# - Cmdlets with the Set verb will overwrite information that already exists. + It 'can Add-Content to a file' { + <# + Try adding this content to the file we created above using + Add-Content. + #> + "Mountains are merely mountains." | ____ -Path $FilePath + + <# + Let's see what happens if we add a whole bunch of things! Fill + in these blanks with whatever you like. + #> - If you followed the example in the 'New' and 'Add' tests, you can use set to do - something to your text file: + '____' | Add-Content -Path $FilePath + '____' | Add-Content -Path $FilePath + '____' | Add-Content -Path $FilePath + '____' | Add-Content -Path $FilePath - $Path = "YOUR PATH.txt" - Set-Content -Path $Path -Value "Sir Kill-A-Lot is the best house robot because of reasons." + # Let's check the contents of the file. + $FileData = Get-Content -Path $FilePath - Before continuing, run this command several times. See what happens, is it the - result you expected? + # How many lines did we end up with? + __ | Should -Be $FileData.Count - You'll see that there's only one line of text in the file. This is because the Set-Content command - will overwrite information that's already there. + <# + We can see that several lines of content were added to the file. + Add-* cmdlets can only append data, they can't overwrite. With + this information, you should be able to determine what the + expected content of the file is at this point. + #> + + $ExpectedContent = @( + 'Mountains are merely mountains.' + '____' + '____' + '____' + 'The road onwards, the road back; which is the shorter?' + ) + + $ExpectedContent | Should -BeExactly $FileData + } + } - Some Set-* cmdlets require the instance to already be present for you to change it; - you'll need to use a New-* cmdlet first to create an instance before you can - overwrite information within it. + Context "Set" { + <# + Cmdlets with the Set verb will overwrite information that already + exists. - A common example one may see working with Office 365 is with calendar permissions. - If a user already has some permissions configured, you can use you use "Set-MailboxFolderPermission" - to change the user's permissions. However, attempting to use an Add cmdlet will fail; - Set-* commands overwrite data, but often can only do so if it already exists. + Some Set-* cmdlets require the instance to already be present for + you to change it; you'll need to use a New-* cmdlet first to create + an instance before you can overwrite information within it. + A common example one may see working with Office 365 is with + calendar permissions. If a user already has some permissions + configured, you can use "Set-MailboxFolderPermission" to change the + user's permissions. #> It 'is for commands that overwrite data' { @@ -145,39 +207,83 @@ Describe "Basic Verbs" { $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required" } - } - Context "Remove" { - <# - Cmdlets with the Remove verb will delete data from an object or data source. + It 'can Set-Content for a file' { + <# + Let's try using Set-Content on our text file from before. But + first, let's check that it still has the contents we added. We + should still have 5 lines in it from before. - If you followed the example in the 'New','Add' and 'Set' tests, you can use Remove-Item to - delete your text file: + If you added extra lines to the file in the Add-Content koan + above, make sure to update the expected line count here! + #> + $LineCount = 5 + Get-Content -Path $FilePath | Should -HaveCount $LineCount + + # Now let's try setting the contents. + "Wherever you are, it's the place you need to be." | Set-Content -Path $FilePath - $Path = "YOUR PATH.txt" - Remove-Item -Path $Path + # So what should be in the file now? + $FileContent = Get-Content -Path $FilePath + "____" | Should -BeExactly $FileContent - Before continuing, run this command a few times. What happens when you try to run it - once the instance has been deleted? + # What happens if we set the contents again? + '____' | Set-Content -Path $FilePath + Get-Content -Path $FilePath | Should -BeExactly "Rest and be kind, you don't have to prove anything." + <# + You'll see that there's only one line of text in the file. This + is because the Set-Content command will completely overwrite + whatever is in the file already. + #> + } + } - You'll see that it fails. Cmdlets with the verb Remove simply remove data; - if the instance you're referring to doesn't exist, then there's nothing available - to remove and it will emit an error message. + Context "Remove" { + <# + Cmdlets with the Remove verb will delete data from an object or data + source. - Returning to Calendar permissions in Office 365, you can use a Remove cmdlet - to completely remove a user's permissions to a calendar. - #> + Once again with calendar permissions in Office 365, you can use a + Remove cmdlet to completely remove a user's permissions to a + calendar. + #> It "is for commands that delete data" { <# - Using Get-Command, find 5 commands with the Remove verb. + Using Get-Command, find 5 commands with the Remove verb. - Replace each ____ with the name of a Remove-* command. - #> + Replace each ____ with the name of a Remove-* command. + #> $Answers = "____", "____", "____", "____", "____" $Answers | Should -BeIn (Get-Command -Verb Remove).Name $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required" } + + It 'can Remove-Item to delete a file' { + <# + We can use Remove-Item to delete the text file we've been + working with. Before we do, let's just double check the file + still exists. 'Leaf' here refers to a file; 'Container' + would be the corresponding type for a folder. + #> + Test-Path $FilePath -PathType Leaf | Should -BeTrue + + # Pester has its own way of checking that files exist. + $FilePath | Should -Exist + + # Use Remove-item to delete the file completely. + ____ -Path $FilePath + + # Let's check it was removed properly. Test-Path $FilePath -PathType Leaf | Should -BeTrue + Test-Path $FilePath | Should -BeFalse + + <# + If we try to remove a file that doesn't exist, we should get + an error. What does that error look like? + #> + $Message = "____" + { Remove-Item -Path $FilePath -ErrorAction Stop } | Should -Throw -ExpectedMessage $Message + } } } diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 65e41e544..b051650c0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,11 +15,11 @@ pr: variables: NupkgArtifactName: 'PSKoans.nupkg' ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - BuildName: '$(Date:yyyy-MM-dd) (#$(BuildID)) $(TeamProject) ($(SourceBranchName))' + Trigger: '$(SourceBranchName)' ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: - BuildName: '$(Date:yyyy-MM-dd) (#$(BuildID)) $(TeamProject) (PR #$(System.PullRequest.PullRequestId))' + Trigger: 'PR #$(System.PullRequest.PullRequestNumber)' -name: '${{ variables.BuildName }}' +name: '$(BuildID)-$(Date:yyyy-MM-dd)$(Rev:.r) $(TeamProject) (${{ variables.Trigger }})' stages: - stage: UploadChangelog