This document provides detailed information about the most commonly used methods in the Azure DevOps Build API.
Retrieves a list of build definitions from a project.
async getDefinitions(
project: string,
name?: string,
repositoryId?: string,
repositoryType?: string,
queryOrder?: BuildInterfaces.DefinitionQueryOrder,
top?: number,
continuationToken?: string,
minMetricsTime?: Date,
definitionIds?: number[],
path?: string,
builtAfter?: Date,
notBuiltAfter?: Date,
includeAllProperties?: boolean,
includeLatestBuilds?: boolean,
taskIdFilter?: string,
processType?: number,
yamlFilename?: string
): Promise<VSSInterfaces.PagedList<BuildInterfaces.BuildDefinitionReference>>
Parameter | Type | Required | Description |
---|---|---|---|
project | string | Yes | Project ID or project name |
name | string | No | Filters to definitions whose names match this pattern |
repositoryId | string | No | Filters to definitions that use this repository |
repositoryType | string | No | Filters to definitions that have a repository of this type |
queryOrder | BuildInterfaces.DefinitionQueryOrder | No | Indicates the order in which definitions should be returned |
top | number | No | The maximum number of definitions to return |
continuationToken | string | No | A continuation token for pagination |
minMetricsTime | Date | No | If specified, indicates the date from which metrics should be included |
definitionIds | number[] | No | A comma-delimited list of definition IDs to retrieve |
path | string | No | Filters to definitions under this folder path. Must be specified using backslashes (e.g., "\TeamA\MicroServices"). Use "\" for the root folder. |
builtAfter | Date | No | Filters to definitions that have builds after this date |
notBuiltAfter | Date | No | Filters to definitions that do not have builds after this date |
includeAllProperties | boolean | No | Whether to return the full definitions (true) or shallow representations (false, default) |
includeLatestBuilds | boolean | No | Whether to return the latest and latest completed builds for this definition |
taskIdFilter | string | No | Filters to definitions that use the specified task |
processType | number | No | Filters to definitions with the given process type |
yamlFilename | string | No | Filters to YAML definitions that match the given filename (requires includeAllProperties=true) |
Returns a Promise that resolves to a paged list of BuildDefinitionReference
objects. Each object contains:
import * as azdev from "azure-devops-node-api";
async function getBuildDefinitions() {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
try {
// Get Build API client
const buildApi = await connection.getBuildApi();
// Get build definitions
const projectName = "YourProject";
const definitions = await buildApi.getDefinitions(
projectName,
undefined, // name
undefined, // repositoryId
undefined, // repositoryType
undefined, // queryOrder
10, // top - limit to 10 results
undefined, // continuationToken
undefined, // minMetricsTime
undefined, // definitionIds
undefined, // path
undefined, // builtAfter
undefined, // notBuiltAfter
true, // includeAllProperties
true // includeLatestBuilds
);
console.log(`Found ${definitions.length} build definitions`);
// Display build definition details
definitions.forEach(def => {
console.log(`Definition: ${def.name} (ID: ${def.id})`);
console.log(` Path: ${def.path}`);
console.log(` Latest Build: ${def.latestBuild ? def.latestBuild.buildNumber : 'None'}`);
console.log(` Latest Status: ${def.latestBuild ? def.latestBuild.status : 'N/A'}`);
console.log(` Latest Result: ${def.latestBuild ? def.latestBuild.result : 'N/A'}`);
console.log('---');
});
return {
success: true,
definitions
};
} catch (error) {
console.error(`Error getting build definitions: ${error.message}`);
return {
success: false,
error: error.message
};
}
}
// Get all build definitions in a project
const definitions = await buildApi.getDefinitions("MyProject");
console.log(`Found ${definitions.length} build definitions`);
definitions.forEach(def => {
console.log(`Definition: ${def.name} (ID: ${def.id})`);
console.log(`Type: ${def.type === BuildInterfaces.DefinitionType.Build ? "Build" : "Release"}`);
if (def.latestBuild) {
console.log(`Latest build: ${def.latestBuild.buildNumber}`);
}
});
// Get build definitions in a specific folder
const folderPath = "\\TeamA\\MicroServices";
const definitionsInFolder = await buildApi.getDefinitions("MyProject", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, folderPath);
console.log(`Found ${definitionsInFolder.length} definitions in ${folderPath}`);
// Get build definitions in the root folder
const rootDefinitions = await buildApi.getDefinitions("MyProject", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "\\");
console.log(`Found ${rootDefinitions.length} definitions in the root folder`);
### Definition References vs. Full Definitions
An important distinction to understand is that the `getDefinitions` method returns `BuildDefinitionReference` objects by default, not complete definition objects with all properties. These references are lightweight objects containing basic information about the build definition.
To understand the difference:
1. **Build Definition Reference**: A lightweight representation that includes:
- Basic properties (id, name, path, revision)
- References to related entities (project, queue)
- Latest build information (if requested with `includeLatestBuilds=true`)
2. **Full Build Definition**: A complete representation that includes everything in the reference plus:
- All build steps/tasks
- All variables and their values
- Complete repository information
- All triggers (continuous integration, scheduled, etc.)
- Retention policy
- Build options and demands
#### Getting Full Definition Details
To get the complete definition with all details, use the `getDefinition` (singular) method:
```typescript
async function getFullDefinitionDetails(definitionId: number) {
// Setup connection and API client
// ... (connection code) ...
const buildApi = await connection.getBuildApi();
// Get the full definition
const projectName = "YourProject";
try {
const fullDefinition = await buildApi.getDefinition(
projectName,
definitionId,
undefined, // revision (optional)
undefined, // minMetricsTime (optional)
undefined, // propertyFilters (optional)
true // includeLatestBuilds
);
console.log(`Definition: ${fullDefinition.name}`);
// Access detailed properties only available in the full definition
console.log(`Number of steps: ${fullDefinition.process?.phases[0]?.steps?.length || 0}`);
console.log(`Number of variables: ${Object.keys(fullDefinition.variables || {}).length}`);
console.log(`Continuous integration trigger enabled: ${fullDefinition.triggers?.some(t => t.triggerType === BuildInterfaces.DefinitionTriggerType.ContinuousIntegration)}`);
return fullDefinition;
} catch (error) {
console.error(`Error retrieving definition: ${error.message}`);
throw error;
}
}
When working with build definitions:
getDefinitions
when you need basic information about multiple definitionsincludeAllProperties=true
with getDefinitions
only when you need all details for multiple definitionsgetDefinition
(singular) when you need complete details about a specific definitionRetrieves a specific build by ID.
async getBuild(
project: string,
buildId: number,
propertyFilters?: string
): Promise<BuildInterfaces.Build>
Parameter | Type | Required | Description |
---|---|---|---|
project | string | Yes | Project ID or project name |
buildId | number | Yes | The ID of the build to retrieve |
propertyFilters | string | No | A comma-delimited list of properties to include in the result |
Returns a Promise that resolves to a Build
object, which contains:
import * as azdev from "azure-devops-node-api";
async function getBuildDetails(buildId: number) {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
// Get Build API client
const buildApi = await connection.getBuildApi();
// Get build details
const projectName = "YourProject";
try {
const build = await buildApi.getBuild(projectName, buildId);
console.log(`Build ${build.buildNumber} (ID: ${build.id})`);
console.log(`Status: ${getBuildStatusText(build.status)}`);
console.log(`Result: ${getBuildResultText(build.result)}`);
console.log(`Started: ${build.startTime}`);
console.log(`Finished: ${build.finishTime}`);
console.log(`Requested by: ${build.requestedBy?.displayName}`);
console.log(`Source branch: ${build.sourceBranch}`);
console.log(`Source version: ${build.sourceVersion}`);
return build;
} catch (error) {
console.error(`Error retrieving build ${buildId}: ${error.message}`);
throw error;
}
}
// Helper functions to convert enum values to readable text
function getBuildStatusText(status: number): string {
const statusMap = {
0: "None",
1: "In Progress",
2: "Completed",
4: "Cancelling",
8: "Postponed",
32: "Not Started"
};
return statusMap[status] || `Unknown (${status})`;
}
function getBuildResultText(result: number): string {
const resultMap = {
0: "None",
2: "Succeeded",
4: "Partially Succeeded",
8: "Failed",
32: "Canceled"
};
return resultMap[result] || `Unknown (${result})`;
}
Retrieves a list of builds based on various filter criteria.
async getBuilds(
project: string,
definitions?: number[],
queues?: number[],
buildNumber?: string,
minTime?: Date,
maxTime?: Date,
requestedFor?: string,
reasonFilter?: BuildInterfaces.BuildReason,
statusFilter?: BuildInterfaces.BuildStatus,
resultFilter?: BuildInterfaces.BuildResult,
tagFilters?: string[],
properties?: string[],
top?: number,
continuationToken?: string,
maxBuildsPerDefinition?: number,
deletedFilter?: BuildInterfaces.QueryDeletedOption,
queryOrder?: BuildInterfaces.BuildQueryOrder,
branchName?: string,
buildIds?: number[],
repositoryId?: string,
repositoryType?: string
): Promise<VSSInterfaces.PagedList<BuildInterfaces.Build>>
Parameter | Type | Required | Description |
---|---|---|---|
project | string | Yes | Project ID or project name |
definitions | number[] | No | A list of definition IDs to filter by |
queues | number[] | No | A list of queue IDs to filter by |
buildNumber | string | No | Filter by build number (append * for prefix search) |
minTime | Date | No | Filter to builds after this date |
maxTime | Date | No | Filter to builds before this date |
requestedFor | string | No | Filter to builds requested by this user |
reasonFilter | BuildInterfaces.BuildReason | No | Filter by the reason the build was created |
statusFilter | BuildInterfaces.BuildStatus | No | Filter by build status |
resultFilter | BuildInterfaces.BuildResult | No | Filter by build result |
tagFilters | string[] | No | Filter to builds with these tags |
properties | string[] | No | A list of properties to retrieve |
top | number | No | Maximum number of builds to return |
continuationToken | string | No | Continuation token for pagination |
maxBuildsPerDefinition | number | No | Maximum number of builds to return per definition |
deletedFilter | BuildInterfaces.QueryDeletedOption | No | Whether to include deleted builds |
queryOrder | BuildInterfaces.BuildQueryOrder | No | The order in which to return builds |
branchName | string | No | Filter to builds from this branch |
buildIds | number[] | No | A list of build IDs to retrieve |
repositoryId | string | No | Filter to builds from this repository |
repositoryType | string | No | Filter to builds from repositories of this type |
Returns a Promise that resolves to a paged list of Build
objects. See the getBuild
method for details on the Build
object properties.
import * as azdev from "azure-devops-node-api";
import * as BuildInterfaces from "azure-devops-node-api/interfaces/BuildInterfaces";
async function getRecentBuilds() {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
// Get Build API client
const buildApi = await connection.getBuildApi();
// Get recent builds
const projectName = "YourProject";
const builds = await buildApi.getBuilds(
projectName,
undefined, // definitions
undefined, // queues
undefined, // buildNumber
new Date(Date.now() - 7 * 24 * 60 * 60000), // minTime (7 days ago)
undefined, // maxTime
undefined, // requestedFor
undefined, // reasonFilter
BuildInterfaces.BuildStatus.Completed, // statusFilter
undefined, // resultFilter
undefined, // tagFilters
undefined, // properties
10, // top
undefined, // continuationToken
undefined, // maxBuildsPerDefinition
undefined, // deletedFilter
BuildInterfaces.BuildQueryOrder.FinishTimeDescending // queryOrder
);
console.log(`Found ${builds.length} builds in the last 7 days`);
// Display build details
builds.forEach(build => {
console.log(`Build ${build.buildNumber} (ID: ${build.id})`);
console.log(` Definition: ${build.definition.name}`);
console.log(` Status: ${getBuildStatusText(build.status)}`);
console.log(` Result: ${getBuildResultText(build.result)}`);
console.log(` Started: ${build.startTime}`);
console.log(` Finished: ${build.finishTime}`);
console.log(` Branch: ${build.sourceBranch}`);
console.log('---');
});
}
// Helper functions to convert enum values to readable text
function getBuildStatusText(status: number): string {
const statusMap = {
0: "None",
1: "In Progress",
2: "Completed",
4: "Cancelling",
8: "Postponed",
32: "Not Started"
};
return statusMap[status] || `Unknown (${status})`;
}
function getBuildResultText(result: number): string {
const resultMap = {
0: "None",
2: "Succeeded",
4: "Partially Succeeded",
8: "Failed",
32: "Canceled"
};
return resultMap[result] || `Unknown (${result})`;
}
Queues a new build for a specified definition.
async queueBuild(
build: BuildInterfaces.Build,
project: string,
ignoreWarnings?: boolean,
checkInTicket?: string,
sourceBuildId?: number,
definitionId?: number
): Promise<BuildInterfaces.Build>
Parameter | Type | Required | Description |
---|---|---|---|
build | BuildInterfaces.Build | Yes | The build to queue |
project | string | Yes | Project ID or project name |
ignoreWarnings | boolean | No | Whether to ignore warnings |
checkInTicket | string | No | The check-in ticket |
sourceBuildId | number | No | The source build ID |
definitionId | number | No | Optional definition ID to queue a build without a body (ignored if there's a valid body) |
Returns a Promise that resolves to a Build
object representing the queued build. See the getBuild
method for details on the Build
object properties.
import * as azdev from "azure-devops-node-api";
import * as BuildInterfaces from "azure-devops-node-api/interfaces/BuildInterfaces";
async function queueNewBuild(definitionId: number, sourceBranch: string) {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
// Get Build API client
const buildApi = await connection.getBuildApi();
// Create build object
const build: BuildInterfaces.Build = {
definition: {
id: definitionId
},
sourceBranch: sourceBranch,
reason: BuildInterfaces.BuildReason.Manual,
priority: BuildInterfaces.BuildPriority.Normal
};
// Queue the build
const projectName = "YourProject";
try {
const queuedBuild = await buildApi.queueBuild(build, projectName);
console.log(`Build queued successfully!`);
console.log(`Build ID: ${queuedBuild.id}`);
console.log(`Build Number: ${queuedBuild.buildNumber}`);
console.log(`Status: ${getBuildStatusText(queuedBuild.status)}`);
console.log(`URL: ${queuedBuild._links.web.href}`);
return queuedBuild;
} catch (error) {
console.error(`Error queuing build: ${error.message}`);
throw error;
}
}
// Helper function to convert enum values to readable text
function getBuildStatusText(status: number): string {
const statusMap = {
0: "None",
1: "In Progress",
2: "Completed",
4: "Cancelling",
8: "Postponed",
32: "Not Started"
};
return statusMap[status] || `Unknown (${status})`;
}
### Setting Build Variables
To set variables for a build, use the `parameters` property of the build object. The `parameters` property takes a stringified JSON object containing the variable names and values:
```typescript
import * as azdev from "azure-devops-node-api";
import * as BuildInterfaces from "azure-devops-node-api/interfaces/BuildInterfaces";
async function queueBuildWithVariables(definitionId: number, sourceBranch: string) {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
// Get Build API client
const buildApi = await connection.getBuildApi();
// Define variables to pass to the build
const buildVariables = {
"DEPLOY_ENVIRONMENT": "Production",
"ENABLE_DEBUG": "false",
"VERSION": "1.2.3",
"RUN_INTEGRATION_TESTS": "true"
};
// Create build object with variables
const build: BuildInterfaces.Build = {
definition: {
id: definitionId
},
sourceBranch: sourceBranch,
reason: BuildInterfaces.BuildReason.Manual,
priority: BuildInterfaces.BuildPriority.Normal,
parameters: JSON.stringify(buildVariables)
};
// Queue the build
const projectName = "YourProject";
try {
const queuedBuild = await buildApi.queueBuild(build, projectName);
console.log(`Build queued successfully with custom variables!`);
console.log(`Build ID: ${queuedBuild.id}`);
console.log(`Build Number: ${queuedBuild.buildNumber}`);
return queuedBuild;
} catch (error) {
console.error(`Error queuing build: ${error.message}`);
throw error;
}
}
Note: Only variables that are defined in the build definition can be set when queuing a build. Setting undefined variables will have no effect.
When queueing builds, be aware that branch policies can impact whether a build can be successfully queued:
Builds for Protected Branches: If you try to queue a build for a branch that has branch policies enabled (like requiring a pull request), the build may be rejected depending on your permissions and the specific policies.
Pull Request Validation Builds: Builds triggered as part of a pull request validation policy behave differently than manually queued builds. They often have different security contexts and variable values.
Build Validation Policy: If a branch has a build validation policy, you may need to queue builds through a pull request rather than directly against the branch.
Example of queueing a build for a feature branch that will eventually be merged into a protected branch:
async function queueFeatureBranchBuild(definitionId: number) {
// Setup connection and API client
// ... (connection code) ...
const buildApi = await connection.getBuildApi();
// Use feature branch instead of protected branch
const build: BuildInterfaces.Build = {
definition: {
id: definitionId
},
sourceBranch: "refs/heads/feature/my-feature", // Use feature branch
reason: BuildInterfaces.BuildReason.Manual
};
try {
const queuedBuild = await buildApi.queueBuild(build, "YourProject");
console.log(`Build queued successfully on feature branch`);
return queuedBuild;
} catch (error) {
if (error.message && error.message.includes("branch policy")) {
console.error("Failed due to branch policy. Try using a feature branch instead.");
} else {
console.error(`Error queueing build: ${error.message}`);
}
throw error;
}
}
Retrieves the logs for a specific build.
async getBuildLogs(
project: string,
buildId: number
): Promise<BuildInterfaces.BuildLog[]>
Parameter | Type | Required | Description |
---|---|---|---|
project | string | Yes | Project ID or project name |
buildId | number | Yes | The ID of the build |
Returns a Promise that resolves to an array of BuildLog
objects. Each BuildLog
object contains:
import * as azdev from "azure-devops-node-api";
async function getBuildLogsAndContent(buildId: number) {
// Setup connection
const orgUrl = "https://dev.azure.com/yourorganization";
const token = process.env.AZURE_DEVOPS_PAT; // Personal Access Token
const authHandler = azdev.getPersonalAccessTokenHandler(token);
const connection = new azdev.WebApi(orgUrl, authHandler);
// Get Build API client
const buildApi = await connection.getBuildApi();
// Get build logs
const projectName = "YourProject";
try {
const logs = await buildApi.getBuildLogs(projectName, buildId);
console.log(`Found ${logs.length} log files for build ${buildId}`);
// Display log metadata
logs.forEach(log => {
console.log(`Log #${log.id}: ${log.type}`);
console.log(` Created: ${log.createdOn}`);
console.log(` Lines: ${log.lineCount}`);
console.log(` URL: ${log.url}`);
});
// Get content for the first log
if (logs.length > 0) {
const logContent = await buildApi.getBuildLogLines(projectName, buildId, logs[0].id);
console.log("\nSample log content (first 10 lines):");
logContent.slice(0, 10).forEach((line, index) => {
console.log(`${index + 1}: ${line}`);
});
}
return logs;
} catch (error) {
console.error(`Error retrieving build logs: ${error.message}`);
throw error;
}
}
### Understanding Log Structure
The logs returned by `getBuildLogs` represent metadata about the available logs, not the actual log content. To get the log content, you need to use the `getBuildLogLines` method:
```typescript
async getBuildLogLines(
project: string,
buildId: number,
logId: number,
startLine?: number,
endLine?: number
): Promise<string[]>
Build logs in Azure DevOps follow a structured format with different types:
Log content often contains ANSI color codes and formatting. When displaying logs, you might want to:
Strip ANSI Color Codes:
function stripAnsiCodes(text: string): string {
return text.replace(/\u001b\[\d+m/g, '');
}
Parse Structured Data:
function extractJsonFromLog(logLines: string[]): any[] {
const results = [];
for (const line of logLines) {
// Look for lines with JSON objects (often wrapped in special markers)
if (line.includes('##[json]')) {
try {
const jsonStr = line.substring(line.indexOf('##[json]') + 8);
results.push(JSON.parse(jsonStr));
} catch (e) {
// Handle parsing errors
}
}
}
return results;
}
Search for Specific Patterns:
function findErrorsInLog(logLines: string[]): string[] {
return logLines.filter(line =>
line.toLowerCase().includes('error') ||
line.includes('##[error]'));
}
For builds with large logs, use the startLine
and endLine
parameters of getBuildLogLines
to retrieve logs in chunks:
// Get logs in chunks of 1000 lines
async function getFullLogInChunks(projectName: string, buildId: number, logId: number) {
const chunkSize = 1000;
let allLines: string[] = [];
let startLine = 0;
let hasMoreLines = true;
while (hasMoreLines) {
const endLine = startLine + chunkSize - 1;
const lines = await buildApi.getBuildLogLines(projectName, buildId, logId, startLine, endLine);
allLines = allLines.concat(lines);
if (lines.length < chunkSize) {
hasMoreLines = false;
} else {
startLine += chunkSize;
}
}
return allLines;
}
In addition to the top 5 methods, these related methods are also useful when working with builds: