Batch delete Artifacts packages in Azure DevOps

At work I recently needed to remove several versions of an npm package published to an Azure DevOps Artifacts feed. The web UI is rather slow to work with when there are a lot of versions present in the feed.

By using the Azure DevOps REST API this type of operation can be done much faster.

Update Packages API

To delete packages in batch we can use the Update Packages API. In these examples I am working with npm packages. But there are matching endpoints for Maven, Nuget, Python and Universal packages.

Create a payload.json

A JSON object is used to specify the operation type and which packages to include.

payload.json:

{
  "operation": 2,
  "packages": [
    { "id": "npm-example-package", "version": "1.0.0" },
    { "id": "npm-example-package", "version": "1.0.1" },
    { "id": "npm-example-package", "version": "1.0.2" }
  ]
}
  • "operation": 2 is operation of type delete.
  • The objects in packages[] details the packages where id corresponds to the package name.

curl example

  1. Generate PAT with az CLI
PERSONAL_ACCESSTOKEN=$(az account get-access-token --query accessToken --output tsv)
  1. Specify the Azure DevOps organization, project and Artifacts feed.
DEVOPS_ORGANIZATION="MyDevOpsOrg"
DEVOPS_PROJECT="MyDevOpsProject"
DEVOPS_FEED_ID="MyFeedId"
  1. curl command
curl --url "https://pkgs.dev.azure.com/${DEVOPS_ORGANIZATION}/${DEVOPS_PROJECT}/_apis/packaging/feeds/${DEVOPS_FEED_ID}/npm/packagesbatch?api-version=7.1-preview.1" \
  --user ":$PERSONAL_ACCESSTOKEN" \
  --header 'Content-Type: application/json' \
  --data @payload.json

If the HTTP response is 202 Accepted the packages included in payload.json will be removed from the feed.

Powershell example

# Variables
$PersonalAccessToken = $(az account get-access-token --query accessToken --output tsv)

$DevopsOrganization = "MyDevOpsOrg"
$DevopsProject = "MyDevOpsProject"
$DevopsFeedId = "MyFeedId"
$Payload = Get-Content -Raw ./payload.json

# Construct request
$Uri = [string]::Format(
  "https://pkgs.dev.azure.com/{0}/{1}/_apis/packaging/feeds/{2}/npm/packagesbatch?api-version=7.1-preview.1",
  $DevopsOrganization, $DevopsProject, $DevopsFeedId
)
$Headers = @{ Authorization = "Bearer $PersonalAccessToken" }

$Params = @{
  Uri         = $Uri
  Headers     = $Headers
  Method      = 'Post'
  Body        = $Payload
  ContentType = 'application/json'
}

Invoke-RestMethod @Params