Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
79d03e9
Move internal versions method to helper class
lbussell Sep 30, 2025
771c236
Factor out parse/serialization logic for internal staging builds
lbussell Sep 30, 2025
9587f72
Add helper method for constructing mock command
lbussell Oct 1, 2025
7c1ec48
Extract ICommand interface from BaseCommand
lbussell Oct 1, 2025
163b241
Use InternalsVisibleTo for update dependencies tests
lbussell Oct 1, 2025
4487387
Add FromStagingPipelineCommand dependency to SyncInternalReleaseCommand
lbussell Oct 1, 2025
bd3497d
Add git restore method
lbussell Oct 1, 2025
cf0d112
Add --repo-root argmuent to existing commands
lbussell Oct 1, 2025
2eb7c5e
Make InternalVersionsHelper into a service
lbussell Oct 1, 2025
398e89f
Split InternalVersions* into one file per type
lbussell Oct 1, 2025
cb32300
Implement first pass at re-applying internal builds
lbussell Oct 2, 2025
996a5f7
Clean up tests and add more comments
lbussell Oct 2, 2025
ff5af1a
Add extra logging to GitRepoHelperFactory
lbussell Oct 2, 2025
4bd8a49
Checkout ref instead of checkout branch for remote branches
lbussell Oct 2, 2025
5545b06
Add extra git logging
lbussell Oct 2, 2025
c4b5cd7
Prevent duplicate logging when calling SpecificCommand more than once
lbussell Oct 2, 2025
9c4414c
Allow multi-line log output
lbussell Oct 2, 2025
9d4f4b0
Use existing CreatePullRequestOptions for SyncInternalReleaseCommand
lbussell Oct 2, 2025
0966724
Make FromStagingPipelineCommand respect repo root
lbussell Oct 2, 2025
a4c388a
Reset using source branch sha instead of branch name
lbussell Oct 2, 2025
79f1a41
Fix argument name for GetToolUpdaters
lbussell Oct 2, 2025
ca0901e
Add helper for shuttling around Manifest version variables and use "b…
lbussell Oct 2, 2025
7167d00
Throw if sub-command had a non-zero exit code
lbussell Oct 2, 2025
c6c5bf9
Fix tests
lbussell Oct 2, 2025
2edd452
Add branch variables to manifest.versions.json
lbussell Oct 2, 2025
3c15992
Reference new Azdo URL extension in SpecificCommand
lbussell Oct 3, 2025
397806b
Always trim org name
lbussell Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions eng/update-dependencies/CreatePullRequestOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@ internal static class CreatePullRequestOptionsExtensions
{
public static string GetManifestVersionsFilePath(this CreatePullRequestOptions options) =>
Path.Combine(options.RepoRoot, "manifest.versions.json");

public static string GetAzdoRepoUrl(this CreatePullRequestOptions options)
{
// Validate that we have all the required pieces to construct the repo URL.
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoOrganization);
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoProject);
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoRepo);
ArgumentException.ThrowIfNullOrWhiteSpace(options.TargetBranch);
ArgumentException.ThrowIfNullOrWhiteSpace(options.SourceBranch);

// AzdoOrganization is a URL like https://dev.azure.com/<org>
// A valid Azure DevOps repository URL is formatted like https://dev.azure.com/<org>/<project>/_git/<repo>
return $"{options.AzdoOrganization.TrimEnd('/')}/{options.AzdoProject}/_git/{options.AzdoRepo}";
Copy link
Member

Choose a reason for hiding this comment

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

This shares the same logic as SyncInternalReleaseCommand.ExecuteAsync. It'd be nice if there was one method to format this URL.

Copy link
Member Author

Choose a reason for hiding this comment

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

I made sure that SpecificCommand and SyncInternalReleaseCommand both use the extension method. Also centralized the trimming into the options class.

}
}
11 changes: 1 addition & 10 deletions eng/update-dependencies/Sync/SyncInternalReleaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,7 @@ ILogger<SyncInternalReleaseCommand> logger

public override async Task<int> ExecuteAsync(SyncInternalReleaseOptions options)
{
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoOrganization);
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoProject);
ArgumentException.ThrowIfNullOrWhiteSpace(options.AzdoRepo);
ArgumentException.ThrowIfNullOrWhiteSpace(options.TargetBranch);
ArgumentException.ThrowIfNullOrWhiteSpace(options.SourceBranch);

// AzdoOrganization is a URL like https://dev.azure.com/<org>
// A valid Azure DevOps repository URL is formatted like https://dev.azure.com/<org>/<project>/_git/<repo>
var remoteUri = new Uri($"{options.AzdoOrganization.TrimEnd('/')}/{options.AzdoProject}/_git/{options.AzdoRepo}");
var remoteUrl = remoteUri.ToString();
var remoteUrl = options.GetAzdoRepoUrl();

// Do not allow syncing starting from an internal branch.
if (options.SourceBranch.StartsWith("internal/", StringComparison.OrdinalIgnoreCase))
Expand Down
27 changes: 16 additions & 11 deletions tests/UpdateDependencies.Tests/SyncInternalReleaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ public sealed class SyncInternalReleaseTests
{
private const string ReleaseBranch = "release/1";
private const string InternalReleaseBranch = $"internal/{ReleaseBranch}";
private const string AzdoOrg = "test-org";
private const string AzdoOrgName = "test-org";
private const string AzdoOrgUrl = $"https://dev.azure.com/{AzdoOrgName}";
private const string AzdoProject = "test-project";
private const string AzdoRepo = "test-repo";
private const string RemoteAzdoUrl = $"https://dev.azure.com/{AzdoOrg}/{AzdoProject}/_git/{AzdoRepo}";
private const string RemoteAzdoUrl = $"{AzdoOrgUrl}/{AzdoProject}/_git/{AzdoRepo}";
private const string LocalRepoPath = "/path/to/local-repo";

/// <summary>
Expand All @@ -27,7 +28,9 @@ public sealed class SyncInternalReleaseTests
/// </summary>
private static readonly SyncInternalReleaseOptions s_defaultOptions = new()
{
RemoteUrl = RemoteAzdoUrl,
AzdoOrganization = AzdoOrgUrl,
AzdoProject = AzdoProject,
AzdoRepo = AzdoRepo,
SourceBranch = ReleaseBranch,
TargetBranch = InternalReleaseBranch
};
Expand All @@ -40,7 +43,9 @@ public async Task WhitespaceArgumentsFails()
{
var options = new SyncInternalReleaseOptions
{
RemoteUrl = " ",
AzdoOrganization = " ",
AzdoProject = " ",
AzdoRepo = " ",
SourceBranch = " ",
TargetBranch = " "
};
Expand Down Expand Up @@ -76,7 +81,7 @@ public async Task CreateInternalBranch()

var repoMock = new Mock<IGitRepoHelper>();
var repoFactoryMock = new Mock<IGitRepoHelperFactory>();
repoFactoryMock.Setup(f => f.CreateAsync(options.RemoteUrl)).ReturnsAsync(repoMock.Object);
repoFactoryMock.Setup(f => f.CreateAsync(options.GetAzdoRepoUrl())).ReturnsAsync(repoMock.Object);

// Setup:
// Target branch does not exist on remote
Expand Down Expand Up @@ -106,7 +111,7 @@ public async Task AlreadyUpToDate()
// not explicitly set up in this test.
var repoMock = new Mock<IGitRepoHelper>(MockBehavior.Strict);
var repoFactoryMock = new Mock<IGitRepoHelperFactory>();
repoFactoryMock.Setup(f => f.CreateAsync(options.RemoteUrl)).ReturnsAsync(repoMock.Object);
repoFactoryMock.Setup(f => f.CreateAsync(options.GetAzdoRepoUrl())).ReturnsAsync(repoMock.Object);

// Setup: Both target and source branches exist on remote.
repoMock.Setup(r => r.Remote.RemoteBranchExistsAsync(options.TargetBranch)).ReturnsAsync(true);
Expand Down Expand Up @@ -143,7 +148,7 @@ public async Task FastForward()
repoMock.Setup(r => r.Remote).Returns(remoteRepoMock.Object);

var repoFactoryMock = new Mock<IGitRepoHelperFactory>();
repoFactoryMock.Setup(f => f.CreateAsync(options.RemoteUrl)).ReturnsAsync(repoMock.Object);
repoFactoryMock.Setup(f => f.CreateAsync(options.GetAzdoRepoUrl())).ReturnsAsync(repoMock.Object);

// Setup: Both target and source branches exist on remote.
repoMock.Setup(r => r.Remote.RemoteBranchExistsAsync(options.TargetBranch)).ReturnsAsync(true);
Expand Down Expand Up @@ -193,8 +198,8 @@ public async Task Sync()
{
var options = s_defaultOptions with
{
CommitterName = "Test User",
CommitterEmail = "[email protected]",
User = "Test User",
Email = "[email protected]",
StagingStorageAccount = "dotnetstage"
};

Expand Down Expand Up @@ -254,8 +259,8 @@ public async Task Sync()
gitScenario.RepoMock.Verify(
repo => repo.Local.CommitAsync(
It.IsAny<string>(),
It.Is<(string Name, string Email)>(author =>
author.Name == options.CommitterName && author.Email == options.CommitterEmail
It.Is<(string Name, string Email)>(
author => author.Name == options.User && author.Email == options.Email
)
),
Times.Exactly(numberOfCommits)
Expand Down
Loading