Future post

Friday, 1 May 2020

If I coded the GitHub Action correctly, this blog post should get published even though I’ve dated it 40 minutes in the future from when I committed it to the repository.

Errors from PowerShell 7 in Azure Pipelines

Thursday, 30 April 2020

I’m aiming to use PowerShell 7 as much as possible, including in Azure Pipelines tasks. I was getting a bit frustrated recently though where I had a task failing, but the log gave absolutely no clue as to why.

eg.

Starting: MyTask
==============================================================================
Task         : PowerShell
Description  : Run a PowerShell script on Linux, macOS, or Windows
Version      : 2.165.0
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/powershell
==============================================================================
Generating script.
========================== Starting Command Output ===========================
"C:\Program Files\PowerShell\7\pwsh.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'D:\a\_temp\be69a030-2e55-4cb5-9f80-98968e90f3b2.ps1'"
##[error]PowerShell exited with code '1'.
Finishing: MyTask

What’s going on? Turns out it’s because PowerShell 7 now defaults to the ‘ConciseView’ for errors and so the error ends up being so concise it isn’t actually logged. I’m not the first to experience this. The fact that the concise output is not logged at all does look like a bug though.

The solution

Set $ErrorView to ‘NormalView’ as the first line of your script - then you’ll see useful error details that will help with diagnosing what the problem is.

$ErrorView = 'NormalView'

Hopefully in the future, they’ll fix the problem with no errors being logged, or enhance the pwsh task so you can set the errorview as a task property outside of the script.

Update 15th May

As Justin mentions in the comments, this problem has been fixed, so no need to prepend your scripts with $ErrorView = 'NormalView' now!

Upgrading WSL2 to Ubuntu 20.04 and running Jekyll

Tuesday, 28 April 2020

Ubuntu LTS 20.04 just came out, and you can either install into WSL2 from the Windows Store, or if you already had Ubuntu for WSL then you can upgrade that in place using sudo do-release-upgrade -d.

There’s a few confirmation prompts along the way. Eventually you’ll get to a point where it wants to reboot. The trouble is if you try sudo reboot it will complain that you’re not running systemd and give up.

The solution is to jump back to Windows and run wsl --shutdown, then relaunch Ubuntu and it should be happy.

Jekyll

Having a freshly upgraded install of Ubuntu, I thought it was time I got a local copy of Jekyll so I could preview my blog posts.

To ensure that I’m using the same Gems that GitHub Pages use, I updated my Gemfile to just reference the github-pages gem.

source 'https://rubygems.org'

gem 'github-pages'

And then install Jekyll prerequisites:

sudo apt-get install ruby-full -y
sudo apt-get install build-essential dh-autoreconf -y
sudo apt install zlibc -y
sudo apt install libxml2-dev -y
sudo apt install libxslt-dev -y

Tell Ruby to install Gems locally (so we don’t need sudo)

echo 'export GEM_HOME=~/.ruby/' >> ~/.bashrc
echo 'export PATH="$PATH:~/.ruby/bin"' >> ~/.bashrc
source ~/.bashrc
gem update

gem install pkg-config -v "~> 1.1"
gem install nokogiri -- --use-system-libraries

bundle install

Using the Developer PowerShell Visual Studio with PowerShell 7

Monday, 27 April 2020

One of the nice new features introduced in Visual Studio 2019 16.2 was the Developer PowerShell for VS 2019 - a nice accompaniment to the existing cmd.exe based Developer Command Prompt for VS 2019.

Windows Start Menu showing Developer PowerShell.

I use PowerShell as much as possible, and for a long time now I’ve made a habit of updating my profile.ps1 so that all the Visual Studio tools are available from the PowerShell command prompt. Previously this required running the old VsDevCmd.bat batch file and capturing the environment variables it set to then bring them into the PowerShell process. You can see an example here.

But now there’s first class support for integrating Visual Studio tooling into your PowerShell environment.

If you take a look at the Windows Start Menu shortcut that’s added, you’ll see it’s defined with a target similar to this:

C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell f9f5056f}"

With the release of PowerShell Core 6, and now PowerShell 7, I’m now favouring these latest releases of PowerShell over the ‘legacy’ Windows PowerShell 5.1. The problem was until recently, the assembly you see referenced in the shortcut above only worked in Windows PowerShell. It wasn’t compatible with PowerShell Core. Pleasingly this was fixed in Visual Studio 2019 16.5.

So now in your PowerShell 7 profile, you can add:

Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -InstanceId 9034d7ab

And you’ll get the full DevShell experience: !Windows Terminal with PowerShell 7 and Visual Studio integration

There’s just one catch - notice that InstanceId? That’s unique for every machine. You can either grab the value out of the properties of the Start Menu shortcut, or run vswhere -property instanceId which will return the instanceId of the newest instance of Visual Studio.

4 doesn't go into 3 part 2

Sunday, 26 April 2020

Last time, we’d figured out a strategy for getting our data up into Azure Artifacts. The problem was that we are using SemVer pre-release notation, and the Azure Artifacts command line and Azure Pipelines task don’t support quering pre-release versions using wildcards.

The CLI tools and Pipelines task will work if we know the exact pre-release version required, but how to find that out? The Azure DevOps Services REST API.

Here’s an example PowerShell script you could use to find out the latest version of a package named ‘mypackage’. It sets a pipeline variable that can be used in subsequent Azure Pipeline tasks.

$url = "https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?api-version=5.1-preview.1&packageNameQuery=mypackage"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "",$env:SYSTEM_ACCESSTOKEN)))
$result = Invoke-RestMethod -Uri $url -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$packageVersion = $result.value.versions.normalizedVersion
Write-Host "##vso[task.setvariable variable=packageVersion]$packageVersion"

We’re making use of the packageNameQuery parameter to filter by the package name, but there are other filtering options available. You could also do more filtering on the JSON data that the REST API returns.

Now we can use the Universal Package task, requesting the specific version. eg.

# Download Universal Package
steps:
- task: [email protected]
  displayName: 'Universal download'
  inputs:
    downloadDirectory: Application
    vstsFeed: '00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000001'
    vstsFeedPackage: imagemagick
    vstsPackageVersion: '$(packageVersion)'