Skip to content

Conversation

Copy link

Copilot AI commented Oct 30, 2025

Upgrades azure-devops-node-api from 6.5.0 to 15.1.1 to resolve 3 critical CVEs (auth leak in typed-rest-client, RCE in underscore). Includes TypeScript 2.8→5.9 upgrade and adaptation to Azure DevOps API breaking changes.

Security Fixes

  • typed-rest-client: Fixed authentication data leak to 3rd parties
  • underscore: Fixed arbitrary code execution vulnerability
  • Result: 0 vulnerabilities (npm audit)

Azure DevOps API Breaking Changes

Method Renames

// Before (v6)
witProcessApi.getProcesses()
witProcessApi.getProcessById(id)
witProcessApi.addWorkItemTypeRule(rule, processId, witRefName)

// After (v15)
witProcessApi.getListOfProcesses()
witProcessApi.getProcessByItsId(id)
witProcessApi.addProcessWorkItemTypeRule(rule, processId, witRefName)

Fields API Restructure

Fields moved from process-scoped to collection-scoped API:

// Before: Process-level fields
const fields = await witProcessApi.getFields(processId);
// Returns: WITProcessInterfaces.FieldModel[]

// After: Collection-level fields
const fields = await witApi.getFields();
// Returns: WITInterfaces.WorkItemField[]

Added converters WITToWITProcessDefinitionsFieldModel() and WITToWITProcessDefinitionsFieldType() to handle type system differences (FieldType enums have different numeric values: String is 0 vs 1).

Type System Changes

// Process validation
process.properties.class !== ProcessClass.Derived  // Old
process.customizationType === CustomizationType.System  // New

// Rule filtering
!rule.isSystem  // Old
rule.customizationType !== CustomizationType.System  // New

// Behavior matching
behaviorsOnTarget.some(b => b.id === behavior.id)  // Old
behaviorsOnTarget.some(b => b.referenceName === behavior.id)  // New

Interface Updates

  • FieldRuleModelProcessRule with CreateProcessRuleRequest for creation
  • Field access: field.idfield.referenceName
  • ProcessInfo: removed nested properties.class, now top-level customizationType

Code Quality

  • Removed unsafe type assertions (as any)
  • Added explicit return type annotations for API calls
  • Fixed typo in error message

Testing Recommendations

Critical paths requiring validation:

  • Export/import with custom fields (especially picklists, identity types)
  • Rule migration (verify system rules excluded)
  • Behavior migration (process & work item type level)
  • Process type validation (Inherited/Custom accepted, System rejected)
  • Large processes (50+ fields, 20+ work item types)
Original prompt

Help me upgrade dependencies to the latest. There may be breaking changes in the Azure DevOps api that may require logic changes, make sure to highlight those so we make sure to test correctly.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits October 30, 2025 23:26
…g change fixes

Co-authored-by: MOlausson <7904771+MOlausson@users.noreply.github.com>
Co-authored-by: MOlausson <7904771+MOlausson@users.noreply.github.com>
Copilot AI changed the title [WIP] Upgrade dependencies and address Azure DevOps API changes Upgrade dependencies to resolve critical vulnerabilities and address Azure DevOps API v15 breaking changes Oct 30, 2025
Copilot AI requested a review from MOlausson October 30, 2025 23:36
@MOlausson MOlausson requested a review from Copilot December 7, 2025 18:53
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades azure-devops-node-api from v6.5.0 to v15.1.1 to resolve 3 critical CVEs and adapt to breaking API changes. Key changes include updating method names, migrating from process-scoped to collection-scoped field APIs, and handling new type system structures. The PR also adds retry logic for network resilience and comprehensive JSDoc documentation.

Key Changes:

  • Security: Upgraded dependencies to eliminate critical CVEs in typed-rest-client and underscore
  • API Compatibility: Updated all Azure DevOps API calls to v15 method names and structures
  • Type Safety: Added explicit return types and removed unsafe type assertions

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
package.json Upgraded azure-devops-node-api (6.5.0→15.1.1), TypeScript (2.8→5.9), and related dependencies
src/common/Utilities.ts Added WIT↔WITProcessDefinitions converters, retry logic, behavior parent resolution, and URL validation
src/common/ProcessExporter.ts Updated API calls to v15 methods (getListOfProcesses, getProcessByItsId, getProcessBehaviors, getProcessWorkItemTypeRules)
src/common/ProcessImporter.ts Migrated to collection-scoped fields API, updated rule/behavior filtering, added retry handling for API v15 limitations
src/common/Engine.ts Added configurable retry mechanism with exponential backoff for network timeout errors
src/common/Interfaces.ts Changed fields type from FieldModel[] to WorkItemField[], added retry configuration options
src/common/Constants.ts Improved configuration template comments for clarity
src/nodejs/Main.ts Fixed typo in error message, improved comments, added Engine configuration call
src/nodejs/NodeJsUtilities.ts Added JSDoc comments for all public methods
src/nodejs/FileLogger.ts Added JSDoc comments
src/nodejs/ConfigurationProcessor.ts Added JSDoc comments and overwriteProcessOnTarget parameter handling
src/common/Logger.ts Updated JSDoc comment
src/common/Errors.ts Added JSDoc comments for all error classes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +99 to +107

if (processModel.properties && processModel.properties.parentProcessTypeId) {
parentProcessTypeId = processModel.properties.parentProcessTypeId;
} else if ((processModel as any).parentProcessTypeId) {
parentProcessTypeId = (processModel as any).parentProcessTypeId;
} else if ((processModel as any).parentTypeId) {
parentProcessTypeId = (processModel as any).parentTypeId;
}

Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple type assertions with as any bypass TypeScript's type safety. Consider creating a union type or type guard to handle different API response structures more safely.

Suggested change
if (processModel.properties && processModel.properties.parentProcessTypeId) {
parentProcessTypeId = processModel.properties.parentProcessTypeId;
} else if ((processModel as any).parentProcessTypeId) {
parentProcessTypeId = (processModel as any).parentProcessTypeId;
} else if ((processModel as any).parentTypeId) {
parentProcessTypeId = (processModel as any).parentTypeId;
}
// Type guards for different possible shapes
function hasPropertiesParentProcessTypeId(obj: any): obj is { properties: { parentProcessTypeId: string } } {
return obj && obj.properties && typeof obj.properties.parentProcessTypeId === "string";
}
function hasParentProcessTypeId(obj: any): obj is { parentProcessTypeId: string } {
return obj && typeof obj.parentProcessTypeId === "string";
}
function hasParentTypeId(obj: any): obj is { parentTypeId: string } {
return obj && typeof obj.parentTypeId === "string";
}
if (hasPropertiesParentProcessTypeId(processModel)) {
parentProcessTypeId = processModel.properties.parentProcessTypeId;
} else if (hasParentProcessTypeId(processModel)) {
parentProcessTypeId = processModel.parentProcessTypeId;
} else if (hasParentTypeId(processModel)) {
parentProcessTypeId = processModel.parentTypeId;
}

Copilot uses AI. Check for mistakes.
Comment on lines +204 to +211
} else if (behavior.inherits && (behavior.inherits as any).behaviorRefName) {
// New API structure: inherits.behaviorRefName
inheritsId = (behavior.inherits as any).behaviorRefName;
} else if ((behavior as any).inheritsId) {
inheritsId = (behavior as any).inheritsId;
} else if ((behavior as any).parentId) {
inheritsId = (behavior as any).parentId;
}
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple type assertions with as any bypass TypeScript's type safety. Consider creating a union type or type guard to handle different API response structures more safely.

Copilot uses AI. Check for mistakes.

// Extract behavior ID from various API property structures
let behaviorId = behavior.id;
if (!behaviorId || behaviorId === 'undefined' || behaviorId.trim() === '') {
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking if behaviorId === 'undefined' compares against the string literal 'undefined', not the undefined value. This should be behaviorId === undefined or remove this check since the previous condition !behaviorId already handles undefined.

Copilot uses AI. Check for mistakes.
}

// Final validation - ensure we have a valid behavior ID
if (!behaviorId || behaviorId === 'undefined' || behaviorId.trim() === '') {
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate check: checking if behaviorId === 'undefined' compares against the string literal 'undefined', not the undefined value. This should be behaviorId === undefined or remove this check since !behaviorId already handles undefined.

Copilot uses AI. Check for mistakes.
const behaviorId = behavior.id || (behavior as any).referenceName || (behavior as any).behaviorId || behavior.name;

// Skip behaviors with invalid IDs
if (!behaviorId || behaviorId === 'undefined' || behaviorId.trim() === '') {
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking if behaviorId === 'undefined' compares against the string literal 'undefined', not the undefined value. This should be behaviorId === undefined or remove this check since !behaviorId already handles undefined.

Suggested change
if (!behaviorId || behaviorId === 'undefined' || behaviorId.trim() === '') {
if (!behaviorId || behaviorId.trim() === '') {

Copilot uses AI. Check for mistakes.
return await Engine.Task(() => this._witProcessApi.getProcesses(), `Get processes on target account`);
}, () => new ValidationError("Failed to get processes on target acccount, check account url, token and token permission."));
return await Engine.Task(() => this._witProcessApi.getListOfProcesses(), `Get processes on target account`);
}, () => new ValidationError("Failed to get processes on target account, check account url, token and token permission."));
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message uses 'acccount' (with three c's). This appears to be a typo and should be 'account'.

Copilot uses AI. Check for mistakes.
Comment on lines +71 to 72
const fieldExist = fieldsOnTarget.some(targetField => targetField.referenceName === sourceField.referenceName);
if (!fieldExist) {
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Variable name 'fieldExist' should be 'fieldExists' to follow proper English grammar and naming conventions.

Suggested change
const fieldExist = fieldsOnTarget.some(targetField => targetField.referenceName === sourceField.referenceName);
if (!fieldExist) {
const fieldExists = fieldsOnTarget.some(targetField => targetField.referenceName === sourceField.referenceName);
if (!fieldExists) {

Copilot uses AI. Check for mistakes.
@MOlausson MOlausson changed the title Upgrade dependencies to resolve critical vulnerabilities and address Azure DevOps API v15 breaking changes Upgrade dependencies to resolve critical vulnerabilities and address Azure DevOps API v15 breaking changes AB#180 Dec 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants