Delete Leased Builds
This is used for deleting leased builds in an Azure DevOps Project. It is useful for when trying to delete a pipeline that has leased builds preventing the deletion.
import requests
import base64
# Example https://dev.azure.com/{org}/{project}
project_url = "https://dev.azure.com/{org}/{project}"
pat = "your_pat_here"
encoded_pat = base64.b64encode(f":{pat}".encode()).decode()
# Example https://dev.azure.com/{org}/{project}/_build?definitionId=17
build_definition_ids = [17]
base_api_url = f"{project_url}/_apis/build"
request_headers = { "Authorization": f"Basic {encoded_pat}" }
def getBuildByDefinition(definition_id):
params = { "definitions": definition_id, "statusFilter": "completed", "api-version": "6.1-preview.7" }
response = requests.get(f"{base_api_url}/builds", headers=request_headers, params=params, verify=True)
response.raise_for_status()
return response.json()["value"]
def getBuildLeases(build_id):
params = { "api-version": "6.1-preview.1" }
response = requests.get(f"{base_api_url}/builds/{build_id}/leases", headers=request_headers, params=params, verify=True)
response.raise_for_status()
return response.json()["value"]
def deleteBuildLease(lease_id):
params = { "api-version": "6.1-preview.1" }
response = requests.delete(f"{base_api_url}/retention/leases?ids={lease_id}", headers=request_headers, params=params, verify=True)
response.raise_for_status()
return response.status_code == 204
for definition_id in build_definition_ids:
builds = getBuildByDefinition(definition_id)
for build in builds:
build_id = build["id"]
if build["retainedByRelease"] == True:
leases = getBuildLeases(build_id)
for lease in leases:
lease_id = lease["leaseId"]
if lease["protectPipeline"] == True:
delete_result = deleteBuildLease(lease_id)
print(f"Lease {lease_id} of build {build_id} delete status => {delete_result}")
else:
print(f"Build {build_id} is not retained by release")