Skip to content

Conversation

@surajitshil-03
Copy link
Contributor

@surajitshil-03 surajitshil-03 commented Oct 15, 2025

Context

This PR implements Node 24 support for Azure Pipelines Agent to enable pipeline tasks to use the latest Node.js runtime (v24.10.0). This upgrade is part of the ongoing effort to keep the agent's Node.js runtime current with LTS releases and provide enhanced performance and security features to pipeline users.

The implementation adds Node 24 as the highest priority handler while maintaining backward compatibility with existing Node versions.


Description

  • Added Node 24 Handler Infrastructure: Implemented Node24HandlerData class with Priority=1 (highest)
  • Enhanced Agent Knobs: Added three Node 24 configuration knobs:
    • UseNode24: Forces Node 24 for all Node-based tasks
    • UseNode24InUnsupportedSystem: Enables Node 24 on unsupported systems
    • UseNode24ToStartContainer: Uses Node 24 for container job initialization
  • Updated Handler Selection Logic: Modified NodeHandler.cs with Node24→Node20→Node16 fallback chain
  • Extended Build System: Updated externals.sh to download Node 24.10.0 for 10 platforms
  • Added Telemetry Support: Implemented EmitHostNode24FallbackTelemetry for monitoring usage
  • Container Support: Added Node 24 support in ContainerOperationProvider.cs

Risk Assessment (Low / Medium / High)

Risk Level: Low

  • Backward Compatibility: Complete fallback mechanism ensures existing pipelines continue working
  • Feature Flag Protection: Gated behind AGENT_USE_NODE24 environment variable (default: false)
  • Isolated Code Paths: New Node 24 logic doesn't modify existing handler implementations
  • Gradual Rollout: Can be enabled selectively per agent or pipeline
  • Established Pattern: Follows proven implementation pattern from Node 20 integration

Unit Tests Added or Updated (Yes / No)

NodeHandlerL0.cs

  • Added "node24" to UseNewNodeForNewNodeHandler() parameterised test

  • Updated ResetNodeKnobs() method to include Node 24 environment variables

L1TestBase.cs

  • Updated ResetNodeKnobs() method to reset Node 24 knobs in L1 tests

Additional Testing Performed

Integration Testing:

Pipeline Execution Validation

  • Tested Node 24 pipeline execution with AGENT_USE_NODE24=true
image
  • Verified handler selection logs show by checking the logs showing Handler selected successfully - Type: Microsoft.VisualStudio.Services.Agent.Worker.Node24HandlerData
image
  • Confirmed task execution uses: [Using node path: <agent_path>\externals\node24\bin\node.exe]
image

Change Behind Feature Flag (Yes / No)

Yes - The implementation is fully gated behind the AGENT_USE_NODE24 environment variable:

  • Default value: false (no impact on existing deployments)
  • Explicit opt-in required for Node 24 activation
  • Can be controlled per-agent, per-pipeline, or globally
  • Allows gradual rollout and easy rollback if issues arise

Tech Design / Approach

Design Reviewed: Implementation follows established Node handler pattern from Node 20/16 integration
Architecture Decisions:

  • Priority-based handler selection (Node24=1, Node20=2, Node16=3)
  • Environment-driven configuration through AgentKnobs
  • Comprehensive fallback mechanism for compatibility
  • Telemetry integration for usage monitoring

Documentation Changes Required (Yes/No)

Documentation updates needed:

  • Agent configuration guide for Node 24 knobs
  • Pipeline task compatibility matrix
  • Migration guide for Node 24 adoption
  • Troubleshooting guide for Node version issues
  • Release notes documenting Node 24 availability

Logging Added/Updated (Yes/No)

  • Added structured logging for Node 24 handler selection: "Handler selected successfully - Type: Node24HandlerData"
  • Added diagnostic logging: "Task.json has node24 handler data: True"
  • Added knob validation logging: "Found UseNode24 knob, using node24 for node tasks: True"
  • Added fallback telemetry: EmitHostNode24FallbackTelemetry method
  • Added Node path debugging: "Using node path: ...\externals\node24\bin\node.exe"

All logging follows existing patterns and doesn't expose sensitive data


Telemetry Added/Updated (Yes/No)

  • Node Handler Selection Telemetry: Integrated with existing UseNewNodeHandlerTelemetry framework
  • Fallback Event Tracking: Added EmitHostNode24FallbackTelemetry for monitoring Node 24→20→16 transitions
  • Handler Priority Metrics: Node 24 selection events tagged with handler type and priority
  • Container Operation Telemetry: Node 24 container job initialization tracking
  • Error Tracking: GLIBC compatibility error telemetry for unsupported systems

Rollback Scenario and Process (Yes/No)

  • Rollback plan is documented.

Dependency Impact Assessed and Regression Tested (Yes/No)

  • All impacted internal modules, APIs, services, and third-party libraries are analyzed.
  • Results are reviewed and confirmed to not break existing functionality.

@surajitshil-03 surajitshil-03 marked this pull request as ready for review October 17, 2025 13:25
@surajitshil-03 surajitshil-03 requested review from a team as code owners October 17, 2025 13:25
@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@surajitshil-03 surajitshil-03 marked this pull request as draft October 17, 2025 13:26
@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@surajitshil-03 surajitshil-03 marked this pull request as ready for review October 22, 2025 13:03
@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

if (PlatformUtil.HostOS == PlatformUtil.OS.Linux)
{
if (supportsNode20.HasValue)
if (!useNode20InUnsupportedSystem)
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't node24 check be before node20?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here both are if statement and it will check for both node20 as well as node24. So I think there will be no impact due to order of execution.

}
else
{
node24ResultsInGlibCErrorHost = await CheckIfNode24ResultsInGlibCError();
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of copying the complete logic, as we are using the same glibc error versions, can we make CheckIfNode24ResultsInGlibCError parameterized and pass node version which should be used instead of copying the code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have tried parameterizing the complete if and else statement, but it was becoming bit complex. But I have parameterized the CheckIfNode<>ResultsInGlibcError function into CheckIfNodeResultsInGlibCError()

{
Trace.Info($"Found UseNode24 knob, using node24 for node tasks: {useNode24}");

if (node24ResultsInGlibCError)
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of replicating the code, can we please move this in a method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Parameterized the checks using the function: GetNodeFolderWithFallback()

{
if (inContainer)
{
ExecutionContext.Warning($"The container operating system doesn't support Node24. Using Node20 instead. " +
Copy link
Contributor

Choose a reason for hiding this comment

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

why don't we have "https://github.com/nodesource/distributions" in this message?

Copy link
Contributor

Choose a reason for hiding this comment

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

should we make a single method and have these messages in constants, which are picked based on a parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Created a new function: NodeFallbackWarning()

public sealed class Node16HandlerData : BaseNodeHandlerData
{
public override int Priority => 2;
public override int Priority => 3;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should shift this by +100 eg, 101, 102, 103...
with this in future we can add new node versions with single change

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. updated the priority orders by +100 but kept the priority this class same as is:
public sealed class AgentPluginHandlerData : HandlerData
{
public override int Priority => 0;
}

@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

nameof(UseNode24),
"Forces the agent to use Node 24 handler for all Node-based tasks",
new RuntimeKnobSource("AGENT_USE_NODE24"),
new EnvironmentKnobSource("AGENT_USE_NODE24"),
Copy link
Contributor

Choose a reason for hiding this comment

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

this should have pipeline feature source as well

@surajitshil-03 surajitshil-03 force-pushed the users/surajitshil-03/node_24_upgrade branch from 4516bb0 to b7f511c Compare October 23, 2025 19:34
@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@surajitshil-03
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@surajitshil-03 surajitshil-03 force-pushed the users/surajitshil-03/node_24_upgrade branch from 51e7b55 to b43c584 Compare October 24, 2025 05:35
@surajitshil-03 surajitshil-03 force-pushed the users/surajitshil-03/node_24_upgrade branch from b43c584 to 9aa7b9e Compare October 24, 2025 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants