Winget Packager in Azure DevOps Pipeline

A couple of months ago a fellow MVP Stephan van Rooij wrote an application called Winget Intune, when I saw this I immediately wanted to use this as a packager in an Azure DevOps Pipeline. So, the idea is to enter a winget package ID and the application is grabbed from winget, packaged, and uploaded to a tenant of your choice.

Prerequisites

There are quite some prerequisites in order to set this up. You need to set up Azure DevOps. This is a link to a blog of mine to do so:

Please use Windows Server (2022), winget is not available for Windows Server core (yet). I use Windows Server core + Azure Container instances typically for my agents.

After that, please install Powershell-core, Winget, and Stephan’s application.

You can use this script to install Winget on Windows Server 2022

Lastly, you need a service principal with enough permissions to upload a package to Intune. You created this service principal in the prepare Azure DevOps part of the prerequisites. Add these permissions to your service principal:

Winget Packager in Azure DevOps Pipeline - Service Principal Permissions

Authentication

I use an Azure Key vault in combination with an Azure DevOps variable group to store the Tenant ID, ClientID & ClientSecret. The preferred method is using a certificate but this is just for testing purposes. In a production environment, please use certificate-based authentication. I use this in my other setups but this is jut for the demo.

Add this Service Principal (ClientID & ClientSecret) with the Tenant ID to an Azure Key Vault and use this naming scheme:

After that, create a variable group in Azure DevOps and link this Azure Key vault to this variable group. This is the result:

In addition, you can see the same naming scheme used because these are secrets that are stored in the Azure Key Vault. This enables us to leverage these secrets without exposing them in any logs or code.

Winget Packager Script for Azure DevOps Pipeline

So, there are 2 parts to the pipeline. The script that packages the application and uploads it to Microsoft Intune and the pipeline itself.

This is the script, you can also find it on GitHub:

[CmdletBinding()]
param (
    [Parameter()][String]$PackageId,
    [Parameter()][String]$TenantID,
    [Parameter()][String]$ClientID,
    [Parameter()][String]$ClientSecret
)

$body = @{
    Grant_Type    = "client_credentials"
    Scope         = "https://graph.microsoft.com/.default"
    Client_Id     = $ClientID
    Client_Secret = $ClientSecret
}

$connection = Invoke-RestMethod `
    -Uri https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token `
    -Method POST `
    -Body $body

$Token = $connection.access_token

$Path = "C:\Package"

If (!(Test-Path $Path)) {
    Write-Output "Creating Package Folder"
    New-Item -Path $Path -ItemType Directory
}
else {
    Write-Output "Package Folder already exists"
}

## Create Winget Package

winget -v

winget-intune package $PackageId --source winget --package-folder $Path

Start-Sleep 5

winget-intune publish $PackageId --package-folder $Path --token $Token

#CleanUp

Remove-Item -Path $Path -Recurse -Force

Please save this in your GIT repo in Azure DevOps as a PowerShell (.ps1) file.

After that, you also need to save the pipeline file. This is the file:

trigger: none

pool:
  name: YOURAGENTPOOL

variables:
- group: YOURVARIABLEGROUP

parameters:
- name: customername
  displayName: Customer Name (Select from dropdown)
  type: string
  values:
  - 'NKOLAB'
  - 'StefanLAB'
- name: packageid
  displayName: Package ID (Winget Package ID)
  type: string
  default: 'Adobe.Acrobat.Reader.64-bit'


stages:
- stage: IntunePackage
  jobs:
  - job: IntunePackage
    steps:
    - task: PowerShell@2
      inputs:
        pwsh: true
        targetType: 'inline'
        script: |

          Powershell\Winget-Intune_Package_Demo.ps1 -packageid ${{parameters.packageid}} -TenantId $(${{parameters.customername}}-TenantID) -ClientId $(${{parameters.customername}}-ClientID) -ClientSecret $(${{parameters.customername}}-ClientSecret)

Please save this file in your GIT repo in Azure DevOps as a YAML (.yml) file.

Make sure you change these variables:

The pool name and the variable group is quite obvious but the customer name is a bit special. It must be the prefix of the Azure Key Vault Secrets:

The Powershell part of the YAML Pipeline forwards these secrets to the pipeline, like so:


Lastly, also check whether this path is correct:

Running the Winget Packager Pipeline

Now, we are ready to run the pipeline. When you run the pipeline the Adobe Acrobat Reader package id is prefilled. That is just for demo purposes.

So, click run:

After that, you can select a customer (Prefix for the credentials in the key vault) and enter a package id:

This is what a run looks like:

Leave a Comment