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

Add Join-Verticals task, use it at the final Join Point #19369

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

dkurepa
Copy link
Member

@dkurepa dkurepa commented Apr 9, 2024

dotnet/source-build#4199
Test run https://dev.azure.com/dnceng/internal/_build/results?buildId=2426483&view=results

A small note, we're publishing VerticalManifests as build artifacts because we want every leg to publish it's own into the same artifact. This is causing some SBOM manifest generation errors. The pipeline still runs as expected, but it's not green

@dkurepa dkurepa requested review from a team as code owners April 9, 2024 13:43
{
List<XDocument> verticalManifests = VerticalManifest.Select(xmlPath => XDocument.Load(xmlPath.ItemSpec)).ToList();

if (!string.IsNullOrEmpty(VerticalSubSet))
Copy link
Member Author

Choose a reason for hiding this comment

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

@ViktorHofer I wasn't able to figure out how to do this in msbuild, so I made it an optional task property, let me know if you're OK with this

Copy link
Member

Choose a reason for hiding this comment

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

I don't think you can have a required parameter that is null.

</Target>

<UsingTask TaskName="Microsoft.DotNet.UnifiedBuild.Tasks.JoinVerticals" AssemblyFile="$(MicrosoftDotNetUnifiedBuildTasksAssembly)" />
<Target Name="JoinVerticals " AfterTargets="Build">
Copy link
Member

Choose a reason for hiding this comment

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

I would call this project "publish-final.proj" and the target "PublishFinal":

Suggested change
<Target Name="JoinVerticals " AfterTargets="Build">
<Target Name="PublishFinal" AfterTargets="Build">

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 don't think we should call it publish-final, as this will also be used to download artifacts for join point builds like we discussed. I named it join-verticals since it can join any number of verticals, including all of them

Copy link
Member

Choose a reason for hiding this comment

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

I was under the impression that we can't directly use this target for the join but if we can, great.

Copy link
Member Author

Choose a reason for hiding this comment

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

We should be able to, there's a property called VerticalSubSet that has a list of verticals we want to join, so it doesn't have to be the full set. On second thought, this isn't a very good name, perhaps VerticalsToJoin is better.
There's also a FlatCopy property, that tells the task how we want it to copy artifacts, if it's set to true, all packages will be in a flat layout in the packages folder, and if it's not, we'll keep the same layout as it is in the artifacts, so for the non final join points we should keep it false. Same goes for assets

@dkurepa
Copy link
Member Author

dkurepa commented Apr 9, 2024

Also not sure if we want to publish binlogs for this, we are using a secret as a property so it would appear there

@premun
Copy link
Member

premun commented Apr 9, 2024

Also not sure if we want to publish binlogs for this, we are using a secret as a property so it would appear there

Which secret? Afaik there's a binlog secret redaction tool in Arcade now - maybe we should run it (maybe it runs automatically).

dkurepa and others added 4 commits April 9, 2024 18:27
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
@dkurepa
Copy link
Member Author

dkurepa commented Apr 9, 2024

Also not sure if we want to publish binlogs for this, we are using a secret as a property so it would appear there

Which secret? Afaik there's a binlog secret redaction tool in Arcade now - maybe we should run it (maybe it runs automatically).

There's an Azdo token we're passing as a property to authenticate to AzDo api

@@ -189,4 +189,9 @@
<PoisonUsageReportFile>$(PackageReportDir)poison-usage.xml</PoisonUsageReportFile>
</PropertyGroup>

</Project>
<PropertyGroup>
<VerticalName Condition="'$(VerticalName)' == ''">DefaultVertical</VerticalName>
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if vertical is an appropriate term to use here. What this captures is a unique build identifier, right? cc @mmitche

Copy link
Member

Choose a reason for hiding this comment

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

Would something like ManifestName make more sense? We have the same in Arcade's Publish.proj: https://github.com/dotnet/arcade/blob/87b015b938e5400d6e57afd7650348c17a764b73/src/Microsoft.DotNet.Arcade.Sdk/tools/Publish.proj#L70

Copy link
Member

Choose a reason for hiding this comment

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

Most repos, like installer, that produce multiple manifests do not call each build a 'vertical', though in essence that is what they are. They also do often have a concept of a primary vertical, but there isn't really any formal term used. It's usually along the lines of: "/p:PublishNugetPackages=true". It's not consistent across repos.

You could just say "ManifestName" here. What differentiates this usage, I think, is that we're really formalizing the 'primary' vertical for join points, and we have to give that some kind of name. Primary/main vertical makes the most sense in that context, vs. "Primary Manifest" or such. Then I think it makes sense to use Vertical here too.

- name: azureDevOpsOrg
value: dnceng
- name: azureDevOpsProject
value: internal
Copy link
Member

Choose a reason for hiding this comment

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

The project value can come from azdo build variables (System.TeamProject)

- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- group: Publish-Build-Assets
- name: azureDevOpsOrg
value: dnceng
Copy link
Member

Choose a reason for hiding this comment

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

You might consider not explicitly specifying this value, and instead using System.CollectionUri. That would be the base URI (w/collection) that would get passed to the task.

- name: azureDevOpsProject
value: public
- name: dn-bot-dnceng-build-rw-code-rw
value: ''
Copy link
Member

Choose a reason for hiding this comment

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

I'm kinda surprised this works as blank, but I like it if it does. Otherwise System.AccessToken would potentially work.

<ProjectReference Include="$(RepositoryEngineeringDir)join-verticals.proj" />
</ItemGroup>

<Target Name="PrintInfo"
Copy link
Member

Choose a reason for hiding this comment

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

Why not print info about the pass being the final pass?

Copy link
Member

Choose a reason for hiding this comment

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

nit: it would be good to include the build pass in the info printed.

{
string relativeUrl = $"build/builds/{buildId}/artifacts?artifactName={artifactName}&api-version={_azureDevOpsApiVersion}";
_logger.LogMessage(MessageImportance.High, $"Downloading artifact information from {relativeUrl}");
HttpResponseMessage response = await _httpClient.GetAsync(relativeUrl);
Copy link
Member

Choose a reason for hiding this comment

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

This functionality probably needs a try/catch w/retry on certain responses.

Copy link
Member

Choose a reason for hiding this comment

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

A common pattern is EnsureSuccessStatusCode() here with the corresponding try/catch and retry

string extractedAssetsPath = Path.Combine(extractPath, artifactName, _assetsFolderName);
string extractedPackagesPath = Path.Combine(extractPath, artifactName, _packagesFolderName);

try{
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
try{
try
{

{
string relativeUrl = $"build/builds/{buildId}/artifacts?artifactName={artifactName}&api-version={_azureDevOpsApiVersion}";
_logger.LogMessage(MessageImportance.High, $"Downloading artifact information from {relativeUrl}");
HttpResponseMessage response = await _httpClient.GetAsync(relativeUrl);
Copy link
Member

Choose a reason for hiding this comment

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

In addition a number of these objects (e.g. HttpResponseMessage) are IDisposable and should have using blocks.

{
foreach (string file in fileNamesToCopy)
{
string sourceFilePath = sourceFiles.FirstOrDefault(f => f.Contains(file, StringComparison.OrdinalIgnoreCase))
Copy link
Member

@mmitche mmitche Apr 18, 2024

Choose a reason for hiding this comment

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

I would use SingleOrDefault here to protect against multiple files with the same name being found in the SourceFiles list. In addition, this use be Path.GetFileName(f) rather than .Contains()

await readStream.CopyToAsync(writeStream, _downloadBufferSize);
}

private void CopyFiles(List<string> fileNamesToCopy, List<string> sourceFiles, string sourceDirectory, string destinationFolder, bool flatCopy)
Copy link
Member

Choose a reason for hiding this comment

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

The need/purpose of this method isn't super obvious. Can you add a comment as to why this is written this way?

{
string verticalName = GetRequiredRootAttribute(verticalManifest, _verticalNameAttribute);

List<string> addedPackageIds = AddMissingElements(packageElements, verticalManifest, _packageElementName);
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a comment as to what might be missing and why?

@dkurepa
Copy link
Member Author

dkurepa commented Apr 30, 2024

Pausing this work for a bit, will pick it up at a later point

Copy link
Member

@ViktorHofer ViktorHofer left a comment

Choose a reason for hiding this comment

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

As part of the installer->sdk repository consolidation we are already switching the VMR over into dotnet/sdk. ETA: today or tomorrow. The last manual code sync happened today and we don't plan on doing another sync. Please close this PR and submit it into dotnet/sdk. Sorry for the inconvenience.

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.

None yet

4 participants