Bulk delete stored npm packages from Azure Artifacts

mdailey77

Matthew Dailey

Posted on April 9, 2022

Bulk delete stored npm packages from Azure Artifacts

At my work we used to store our npm packages in an Azure Artifacts feed. We realized this was no longer necessary since we didn't publish our own custom packages anymore. Plus, over time all the different versions of the stored npm packages were taking up a large amount of space, close to 3GB in our cloud instance.

Using the Azure DevOps REST API, I came up with a Powershell script that will bulk delete all npm packages from an Azure Artifacts feed. You will need to generate a PAT (Personal Access Token) with full privileges regarding packages and paste it into the script code. The organization name and feed id also needs to be added.

If there is a large amount of packages with accompanying versions, the script will need to run multiple times. There is a limit to the number of stored package versions that can be retrieved at one time.

The way the script works is it retrieves all the versions of the stored npm packages, loops through the versions and deletes them. In order to delete any package in Azure Artifacts, be it npm or NuGet, you have to delete the specific package version. The script can be modified in case you want to only delete certain versions of packages by changing the url that retrieves the package versions.

Here is the script. Run it on your local machine.

<# Azure DevOps REST API #>
$url1 = 'https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feed_id}/packages?protocolType=npm&includeAllVersions=true&api-version=7.1-preview.1'

$Token = '{Personal_Access_Token}'

if ($Token -eq "") {
    Write-Host 'PAT not set'
    exit 1
}
$AzureAuthHeader1 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $Token)))

$headers1 = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers1.Add("Authorization", ("Basic {0}" -f $AzureAuthHeader1))
$headers1.Add("Content-Type", "application/json")

$response1 = Invoke-RestMethod -Uri $url1 -Method GET -Headers $headers1

$packages = $response1.value

<# Loops through returned npm package versions and deletes them #>
Foreach ($i in $packages)
{
    $packageName = $i.name
    Write-Host $i.name -BackgroundColor cyan
    $allversions = $i.versions
    Foreach ($v in $allversions) {
        $packageVersion = $v.version
        $url2 = 'https://pkgs.dev.azure.com/{organization}/_apis/packaging/feeds/{feed_id}/npm/{0}/versions/{1}?api-version=7.1-preview.1' -f $packageName, $packageVersion
        $AzureAuthHeader2 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $Token)))

        $headers2 = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
        $headers2.Add("Authorization", ("Basic {0}" -f $AzureAuthHeader2))
        $headers2.Add("Content-Type", "application/json")

        $response2 = Invoke-RestMethod -Uri $url2 -Method DELETE -Headers $headers2
        Write-Host 'deleted' + $response2.value
    }
}
Enter fullscreen mode Exit fullscreen mode

The GitHub Gist link.

💖 💪 🙅 🚩
mdailey77
Matthew Dailey

Posted on April 9, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related