Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate build info from BAR to VMR outputs #4192

Merged
merged 15 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
using Microsoft.DotNet.DarcLib;
using Microsoft.DotNet.DarcLib.Helpers;
using Microsoft.DotNet.DarcLib.VirtualMonoRepo;
using Microsoft.Extensions.Logging;
Expand All @@ -16,26 +18,33 @@ internal class InitializeOperation : VmrOperationBase
{
private readonly InitializeCommandLineOptions _options;
private readonly IVmrInitializer _vmrInitializer;
private readonly IBarApiClient _barClient;

public InitializeOperation(
InitializeCommandLineOptions options,
IVmrInitializer vmrInitializer,
ILogger<InitializeOperation> logger)
ILogger<InitializeOperation> logger,
IBarApiClient barClient)
: base(options, logger)
{
_options = options;
_vmrInitializer = vmrInitializer;
_barClient = barClient;
}

protected override async Task ExecuteInternalAsync(
string repoName,
string? targetRevision,
IReadOnlyCollection<AdditionalRemote> additionalRemotes,
CancellationToken cancellationToken)
=> await _vmrInitializer.InitializeRepository(
{
var build = (await _barClient.GetBuildsAsync(repoName, targetRevision)).SingleOrDefault();
await _vmrInitializer.InitializeRepository(
repoName,
targetRevision,
null,
build?.AzureDevOpsBuildNumber,
build?.Id,
_options.Recursive,
new NativePath(_options.SourceMappings),
additionalRemotes,
Expand All @@ -45,4 +54,5 @@ protected override async Task ExecuteInternalAsync(
_options.GenerateCredScanSuppressions,
_options.DiscardPatches,
cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
using Microsoft.DotNet.DarcLib;
using Microsoft.DotNet.DarcLib.VirtualMonoRepo;
using Microsoft.Extensions.Logging;

Expand All @@ -15,33 +17,42 @@ internal class UpdateOperation : VmrOperationBase
{
private readonly UpdateCommandLineOptions _options;
private readonly IVmrUpdater _vmrUpdater;
private readonly IBarApiClient _barClient;

public UpdateOperation(
UpdateCommandLineOptions options,
IVmrUpdater vmrUpdater,
ILogger<UpdateOperation> logger)
ILogger<UpdateOperation> logger,
IBarApiClient barClient)
: base(options, logger)
{
_options = options;
_vmrUpdater = vmrUpdater;
_barClient = barClient;
}

protected override async Task ExecuteInternalAsync(
string repoName,
string? targetRevision,
IReadOnlyCollection<AdditionalRemote> additionalRemotes,
CancellationToken cancellationToken)
=> await _vmrUpdater.UpdateRepository(
repoName,
targetRevision,
targetVersion: null,
_options.Recursive,
additionalRemotes,
_options.ComponentTemplate,
_options.TpnTemplate,
_options.GenerateCodeowners,
_options.GenerateCredScanSuppressions,
_options.DiscardPatches,
reapplyVmrPatches: false,
cancellationToken);
{
var build = (await _barClient.GetBuildsAsync(repoName, targetRevision)).SingleOrDefault();

await _vmrUpdater.UpdateRepository(
repoName,
targetRevision,
targetVersion: null,
build?.AzureDevOpsBuildNumber,
build?.Id,
_options.Recursive,
additionalRemotes,
_options.ComponentTemplate,
_options.TpnTemplate,
_options.GenerateCodeowners,
_options.GenerateCredScanSuppressions,
_options.DiscardPatches,
reapplyVmrPatches: false,
cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ public void UpdateVersionDetails(

SetAttribute(versionDetails, sourceNode, VersionDetailsParser.UriElementName, sourceDependency.Uri);
SetAttribute(versionDetails, sourceNode, VersionDetailsParser.ShaElementName, sourceDependency.Sha);
if (sourceDependency.BarId != null) {
SetAttribute(versionDetails, sourceNode, VersionDetailsParser.BarIdElementName, sourceDependency.BarId.ToString());
}
}

foreach (DependencyDetail itemToUpdate in itemsToUpdate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class VersionDetailsParser : IVersionDetailsParser
public const string VersionPropsAlternateVersionElementSuffix = "Version";
public const string ShaElementName = "Sha";
public const string UriElementName = "Uri";
public const string BarIdElementName = "BarId";
public const string DependencyElementName = "Dependency";
public const string DependenciesElementName = "Dependencies";
public const string NameAttributeName = "Name";
Expand Down Expand Up @@ -158,7 +159,11 @@ private static List<DependencyDetail> ParseDependencyDetails(XmlNodeList depende
var sha = sourceNode.Attributes[ShaElementName]?.Value?.Trim()
?? throw new DarcException($"Malformed {SourceElementName} section - expected {ShaElementName} attribute");

return new SourceDependency(uri, sha);
if (int.TryParse(sourceNode.Attributes[BarIdElementName]?.Value?.Trim(), out int barId))
{
return new SourceDependency(uri, sha, barId);
}
return new SourceDependency(uri, sha, null);
dkurepa marked this conversation as resolved.
Show resolved Hide resolved
}

private static bool ParseBooleanAttribute(XmlAttributeCollection attributes, string attributeName)
Expand Down
53 changes: 0 additions & 53 deletions src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,57 +55,4 @@ public static string CalculateDotnetToolsJsonElementName(string dependencyName)
{
return dependencyName;
}

/// <summary>
/// Reverse a version in the Arcade style (https://github.com/dotnet/arcade/blob/fb92b14d8cd07cf44f8f7eefa8ac58d7ffd05f3f/src/Microsoft.DotNet.Arcade.Sdk/tools/Version.BeforeCommonTargets.targets#L18)
/// back to an OfficialBuildId + ReleaseLabel which we can then supply to get the same resulting version number.
/// </summary>
/// <param name="repoName">The source build name of the repo to get the version info for.</param>
/// <param name="version">The complete version, e.g. 1.0.0-beta1-19720.5</param>
public static (string BuildId, string ReleaseLabel) DeriveBuildInfo(string repoName, string version)
{
const string fallbackBuildIdFormat = "yyyyMMdd.1";

var nugetVersion = new NuGetVersion(version);

if (string.IsNullOrWhiteSpace(nugetVersion.Release))
{
// Finalized version number (x.y.z) - probably not our code
// Application Insights, Newtonsoft.Json do this
return (DateTime.Now.ToString(fallbackBuildIdFormat), string.Empty);
}

var releaseParts = nugetVersion.Release.Split('-', '.');
if (repoName.Contains("nuget"))
{
// NuGet does this - arbitrary build IDs
return (DateTime.Now.ToString(fallbackBuildIdFormat), releaseParts[0]);
}

if (releaseParts.Length == 3)
{
if (int.TryParse(releaseParts[1], out var datePart) && int.TryParse(releaseParts[2], out var buildPart))
{
if (datePart > 1 && datePart < 8 && buildPart > 1000 && buildPart < 10000)
{
return (releaseParts[2], $"{releaseParts[0]}.{releaseParts[1]}");
}

return (VersionToDate(datePart, buildPart), releaseParts[0]);
}
}

if (releaseParts.Length == 4)
{
// New preview version style, e.g. 5.0.0-preview.7.20365.12
if (int.TryParse(releaseParts[2], out var datePart) && int.TryParse(releaseParts[3], out var buildPart))
{
return (VersionToDate(datePart, buildPart), $"{releaseParts[0]}.{releaseParts[1]}");
}
}

throw new FormatException($"Can't derive a build ID from version {version} (release {string.Join(";", nugetVersion.Release.Split('-', '.'))})");
}

private static string VersionToDate(int date, int build) => $"20{date / 1000}{date % 1000 / 50:D2}{date % 50:D2}.{build}";
}
2 changes: 1 addition & 1 deletion src/Microsoft.DotNet.Darc/DarcLib/Models/VersionDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public record VersionDetails(
IReadOnlyCollection<DependencyDetail> Dependencies,
SourceDependency? Source);

public record SourceDependency(string Uri, string Sha);
public record SourceDependency(string Uri, string Sha, int? BarId);

Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ public class GitInfoFile : MsBuildPropsFile
public string GitCommitHash { get; set; }
public string OfficialBuildId { get; set; }
public string OutputPackageVersion { get; set; }
public string PreReleaseVersionLabel { get; set; }
public bool IsStable { get; set; }
public int? GitCommitCount { get; set; }

public GitInfoFile()
Expand All @@ -43,9 +41,7 @@ protected override void SerializeProperties(XmlElement propertyGroup, Func<strin
{
[nameof(GitCommitHash)] = GitCommitHash,
[nameof(OfficialBuildId)] = OfficialBuildId,
[nameof(OutputPackageVersion)] = OutputPackageVersion,
[nameof(PreReleaseVersionLabel)] = PreReleaseVersionLabel,
[nameof(IsStable)] = IsStable ? "true" : "false",
[nameof(OutputPackageVersion)] = OutputPackageVersion
};

if (GitCommitCount.HasValue)
Expand All @@ -64,8 +60,6 @@ public static GitInfoFile DeserializeFromXml(string path)
GitCommitHash = properties[nameof(GitCommitHash)],
OfficialBuildId = properties[nameof(OfficialBuildId)],
OutputPackageVersion = properties[nameof(OutputPackageVersion)],
PreReleaseVersionLabel = properties[nameof(PreReleaseVersionLabel)],
IsStable = properties[nameof(IsStable)] == "true",
GitCommitCount = properties.TryGetValue(nameof(GitCommitCount), out var count) ? int.Parse(count) : null,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,20 @@ public int CompareTo(ISourceComponent? other)

public class RepositoryRecord : ManifestRecord, IVersionedSourceComponent
{
public RepositoryRecord(string path, string remoteUri, string commitSha, string? packageVersion)
public RepositoryRecord(
string path,
string remoteUri,
string commitSha,
string? packageVersion,
int? barId)
: base(path, remoteUri, commitSha)
{
PackageVersion = packageVersion;
BarId = barId;
}

public string? PackageVersion { get; set; }
public int? BarId { get; set; }
}

public class SubmoduleRecord : ManifestRecord
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface ISourceManifest
void RemoveRepository(string repository);
void RemoveSubmodule(SubmoduleRecord submodule);
void UpdateSubmodule(SubmoduleRecord submodule);
void UpdateVersion(string repository, string uri, string sha, string? packageVersion);
void UpdateVersion(string repository, string uri, string sha, string? packageVersion, int? barId);
VmrDependencyVersion? GetVersion(string repository);
bool TryGetRepoVersion(string mappingName, [NotNullWhen(true)] out ISourceComponent? mapping);
ISourceComponent GetRepoVersion(string mappingName);
Expand All @@ -47,7 +47,7 @@ public SourceManifest(IEnumerable<RepositoryRecord> repositories, IEnumerable<Su
_submodules = [.. submodules];
}

public void UpdateVersion(string repository, string uri, string sha, string? packageVersion)
public void UpdateVersion(string repository, string uri, string sha, string? packageVersion, int? barId)
{
var repo = _repositories.FirstOrDefault(r => r.Path == repository);
if (repo != null)
Expand All @@ -59,10 +59,14 @@ public void UpdateVersion(string repository, string uri, string sha, string? pac
{
repo.PackageVersion = packageVersion;
}
if (barId != null)
{
repo.BarId = barId;
}
}
else
{
_repositories.Add(new RepositoryRecord(repository, uri, sha, packageVersion));
_repositories.Add(new RepositoryRecord(repository, uri, sha, packageVersion, barId));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public interface IVmrInitializer
/// <param name="mappingName">Name of a repository mapping</param>
/// <param name="targetRevision">Revision (commit SHA, branch, tag..) onto which to synchronize, leave empty for HEAD</param>
/// <param name="targetVersion">Version of packages, that the SHA we're updating to, produced</param>
/// <param name="officialBuildId">Azdo build id of the build that's being flown, if applicable</param>
/// <param name="barId">Bar id of the build that's being flown, if applicable</param>
/// <param name="initializeDependencies">When true, initializes dependencies (from Version.Details.xml) recursively</param>
/// <param name="sourceMappingsPath">Path to the source-mappings.json file</param>
/// <param name="additionalRemotes">Additional git remotes to use when fetching</param>
Expand All @@ -29,6 +31,8 @@ Task InitializeRepository(
string mappingName,
string? targetRevision,
string? targetVersion,
string? officialBuildId,
int? barId,
bool initializeDependencies,
LocalPath sourceMappingsPath,
IReadOnlyCollection<AdditionalRemote> additionalRemotes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public interface IVmrUpdater
/// <param name="mappingName">Name of a repository mapping</param>
/// <param name="targetRevision">Revision (commit SHA, branch, tag..) onto which to synchronize, leave empty for HEAD</param>
/// <param name="targetVersion">Version of packages, that the SHA we're updating to, produced</param>
/// <param name="noSquash">Whether to pull changes commit by commit instead of squashing all updates into one</param>
/// <param name="officialBuildId">Azdo build id of the build that's being flown, if applicable</param>
/// <param name="barId">Bar id of the build that's being flown, if applicable</param>
/// <param name="updateDependencies">When true, updates dependencies (from Version.Details.xml) recursively</param>
/// <param name="additionalRemotes">Additional git remotes to use when fetching</param>
/// <param name="componentTemplatePath">Path to VMR's Component.md template</param>
Expand All @@ -30,6 +31,8 @@ Task<bool> UpdateRepository(
string mappingName,
string? targetRevision,
string? targetVersion,
string? officialBuildId,
int? barId,
bool updateDependencies,
IReadOnlyCollection<AdditionalRemote> additionalRemotes,
string? componentTemplatePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ public async Task<ILocalGitRepo> PrepareVmrAsync(
cancellationToken);

_vmrInfo.VmrPath = vmr.Path;
await _dependencyTracker.InitializeSourceMappings();
_sourceManifest.Refresh(_vmrInfo.SourceManifestPath);
await _dependencyTracker.RefreshMetadata();
Copy link
Member

Choose a reason for hiding this comment

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

Did you look in other usages of InitializeSourceMappings whether they can also change to this?

Copy link
Member Author

Choose a reason for hiding this comment

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

From what I saw we could use it almost everywhere, but it'd do some extra work that's not needed

Copy link
Member

Choose a reason for hiding this comment

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

I think it might be for the better if we just remove InitializeSourceMappings and just have RefreshMetadata (or maybe name it LoadMetadata so that we can be always sure we load everything always (and in future, if we add more metadata for instance)

Copy link
Member

Choose a reason for hiding this comment

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

I think we will need to be able to override the sourceMappingPath too


return vmr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,9 @@ protected async Task<bool> UpdateDependenciesAndToolset(
if (sourceElementSha != null)
{
sourceOrigin = new SourceDependency(
build?.GetRepository() ?? Constants.DefaultVmrUri,
sourceElementSha);
build.GetRepository(),
sourceElementSha,
build.Id);

if (versionDetails.Source?.Sha != sourceElementSha)
{
Expand Down
Loading