Skip to main content
Glama
feature.ts3.46 kB
import { WebApi } from 'azure-devops-node-api'; import { GitPullRequestIterationChanges, GitChange, } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { PolicyEvaluationRecord } from 'azure-devops-node-api/interfaces/PolicyInterfaces'; import { AzureDevOpsError } from '../../../shared/errors'; import { createTwoFilesPatch } from 'diff'; export interface PullRequestChangesOptions { projectId: string; repositoryId: string; pullRequestId: number; } export interface PullRequestChangesResponse { changes: GitPullRequestIterationChanges; evaluations: PolicyEvaluationRecord[]; files: Array<{ path: string; patch: string }>; sourceRefName?: string; targetRefName?: string; } /** * Retrieve changes and policy evaluation status for a pull request */ export async function getPullRequestChanges( connection: WebApi, options: PullRequestChangesOptions, ): Promise<PullRequestChangesResponse> { try { const gitApi = await connection.getGitApi(); const [pullRequest, iterations] = await Promise.all([ gitApi.getPullRequest( options.repositoryId, options.pullRequestId, options.projectId, ), gitApi.getPullRequestIterations( options.repositoryId, options.pullRequestId, options.projectId, ), ]); if (!iterations || iterations.length === 0) { throw new AzureDevOpsError('No iterations found for pull request'); } const latest = iterations[iterations.length - 1]; const changes = await gitApi.getPullRequestIterationChanges( options.repositoryId, options.pullRequestId, latest.id!, options.projectId, ); const policyApi = await connection.getPolicyApi(); const artifactId = `vstfs:///CodeReview/CodeReviewId/${options.projectId}/${options.pullRequestId}`; const evaluations = await policyApi.getPolicyEvaluations( options.projectId, artifactId, ); const changeEntries = changes.changeEntries ?? []; const getBlobText = async (objId?: string): Promise<string> => { if (!objId) return ''; const stream = await gitApi.getBlobContent( options.repositoryId, objId, options.projectId, ); const chunks: Uint8Array[] = []; return await new Promise<string>((resolve, reject) => { stream.on('data', (chunk) => chunks.push(Buffer.from(chunk))); stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))); stream.on('error', reject); }); }; const files = await Promise.all( changeEntries.map(async (entry: GitChange) => { const path = entry.item?.path || entry.originalPath || ''; const [oldContent, newContent] = await Promise.all([ getBlobText(entry.item?.originalObjectId), getBlobText(entry.item?.objectId), ]); const patch = createTwoFilesPatch( entry.originalPath || path, path, oldContent, newContent, ); return { path, patch }; }), ); return { changes, evaluations, files, sourceRefName: pullRequest?.sourceRefName, targetRefName: pullRequest?.targetRefName, }; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } throw new Error( `Failed to get pull request changes: ${error instanceof Error ? error.message : String(error)}`, ); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tiberriver256/mcp-server-azure-devops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server