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 task to download files from helix results container #2103

Merged
merged 5 commits into from
Feb 27, 2019

Conversation

safern
Copy link
Member

@safern safern commented Feb 24, 2019

Contributes to: #2076

This pr adds a Task for helix jobs to be able to download a file from the results container after a helix run, i.e testResults.xml or coverage.xml.

  1. Every HelixWorkItem should include a metadata entry to specify which files it needs to download:
<HelixWorkItem Include="WorkItem">
   <DownloadFilesFromResults>testResults.xml</DownloadFilesFromResults>
</HelixWorkItem>
  1. A destination directory in the host machine can be specified through an MSBuild property -- $(HelixResultsDestinationDir).
    • If this property is not set and BUILD_SOURCESDIRECTORY property is available (predefined variable in Azure DevOps), it defaults to $(BUILD_SOURCESDIRECTORY)/artifacts/helixresults.
    • If BUILD_SOURCESDIRECTORY is empty, it would log a warning and will not execute the task.
  2. A directory under this destination folder will be created per each Job created => each HelixTargetQueue for the same payload. This folder will be named with the JobId.
  3. Under this Job directory, there will be a metadata.txt file, that will contain the following information:
HelixQueue=%(SentJob.HelixTargetQueue)
Configuration=$(HelixConfiguration)
Architecture=$(HelixArchitecture)

More metadata can be specified to be written into this file, through and ItemGroup => HelixDownloadResultsMetadata
5. Under the Job directory, there will be a directory for every HelixWorkItem that specified the DownloadFilesFromResults metadata, and under that folder it will contain the files that where available for download.
6. If a file is not found within the container, a Warning will be logged through MSBuild.

The structure of the directory will look as follows:

- HelixResultsDestinationDir \
  - JobId \
    - metadata.txt
    - HelixWorkItemName \
       - downloaded files.

cc: @ViktorHofer @danmosemsft @markwilkie @Chrisboh

Copy link
Contributor

@jonfortescue jonfortescue left a comment

Choose a reason for hiding this comment

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

Overall, I think this looks fine, but it really should be made so that it doesn't undo the work done in #1991.

src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs Outdated Show resolved Hide resolved
@echesakov
Copy link

cc @RussKeldorph @jashook

@safern
Copy link
Member Author

safern commented Feb 26, 2019

@alexperovich @jonfortescue this is ready for another round of reviews.

Inputs="unused"
Outputs="%(SentJob.Identity)">
<ItemGroup>
<_workItemsWithDownloadMetadata Include="@(HelixWorkItem)" Condition="'%(HelixWorkItem.DownloadFilesFromResults)' != ''" />
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 you actually need to empty these item groups before adding things to them. IIRC this will currently write the metadata for jobs 1 and 2 together in the file for 2 because the item group has been filled with both.

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 haven't seen this behavior locally, but it doesn't hurt to empty this item group.

Actually the metadata itemgroup was correctly written for multiple jobs. No duplication at all.

Copy link
Member

Choose a reason for hiding this comment

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

Hrm, I wonder if there is some msbuild magic with batching that is making the items not show up.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe because the ItemGroup is within the scope of the target and since we're batching it creates 2 different copies and evaluations of it? Basically 2 different scopes? @ericstj might know.

Copy link
Member

@ericstj ericstj Feb 26, 2019

Choose a reason for hiding this comment

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

I believe the side-effects of a batched target aren't observable until after all batches of that target run.

Try this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <_newProperty>unset</_newProperty>
  </PropertyGroup>

  <ItemGroup>
    <TestItem Include="Abc" />
    <TestItem Include="123" />
  </ItemGroup>
  
  <Target Name="BatchTarget" Inputs="%(TestItem.Identity)" Outputs="Unused">
    <Message Text="BatchTarget Property: $(_newProperty)" Importance="High" />
    <ItemGroup>
      <_newItem Include="@(TestItem)" />
    </ItemGroup>
    <PropertyGroup>
      <_newProperty>@(TestItem)</_newProperty>
    </PropertyGroup>
    <Message Text="BatchTarget: @(_newItem)" Importance="High" />
  </Target>
  
  <Target Name="TestTarget" DependsOnTargets="BatchTarget">
    <Message Text="TestTarget Property: $(_newProperty)" Importance="High" />
    <Message Text="TestTarget: @(_newItem)" Importance="High" />
  </Target>

</Project>

Output of this is:

  BatchTarget Property: unset
  BatchTarget: Abc
  BatchTarget Property: unset
  BatchTarget: 123
  TestTarget Property: 123
  TestTarget: Abc;123

Copy link
Member Author

Choose a reason for hiding this comment

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

Since we don't intend to use this items outside the target I guess we're safe on leaving it as is.

Copy link
Member

@alexperovich alexperovich left a comment

Choose a reason for hiding this comment

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

:shipit:

@ericstj
Copy link
Member

ericstj commented Feb 27, 2019

DownloadFromResultsContainer.cs(100,36): error CS1501: No overload for method 'DownloadToFileAsync' takes 3 arguments [D:\j\_work\1\s\src\Microsoft.DotNet.Helix\Sdk\Microsoft.DotNet.Helix.Sdk.csproj]

Hmm, do you need a newer Azure storage client? https://docs.microsoft.com/en-us/dotnet/api/microsoft.windowsazure.storage.blob.cloudblob.downloadtofileasync?view=azure-dotnet#Microsoft_WindowsAzure_Storage_Blob_CloudBlob_DownloadToFileAsync_System_String_System_IO_FileMode_System_Threading_CancellationToken_

@safern
Copy link
Member Author

safern commented Feb 27, 2019

Hmm, do you need a newer Azure storage client?

Yes, they actually split up the new version into multiple packages. They stopped building WindowsAzure.Storage and created multiple packages. So figuring out which ones we need.

@safern
Copy link
Member Author

safern commented Feb 27, 2019

This is actually what I had to change to consume the new Azure SDK since they had some breaking changes and split the packages: 49cb506

FYI: @Anipik since I changed dependencies and namespaces on the CommitManager.

@safern
Copy link
Member Author

safern commented Feb 27, 2019

This is actually what I had to change to consume the new Azure SDK since they had some breaking changes and split the packages: 49cb506
FYI: @Anipik since I changed dependencies and namespaces on the CommitManager.

Actually I just deleted the commit, Helix.SDK AzurePipelines task was not happy with the Newtonsoft upgrade required by the new azure SDKs. I will leave it as is, without flowing the cancellation token to DowloadToFileAsync since I don't have much time to invest on doing the upgrades, will revisit later to fix it if need it.

@ericstj
Copy link
Member

ericstj commented Feb 27, 2019

Helix.SDK AzurePipelines task was not happy with the Newtonsoft upgrade required by the new azure SDKs

Yeah it probably needs the AssemblyResolver

I'm ok with you undoing the cancellation for now, but it's something you should consider moving forward for tasks which do long running things. Not implementing cancellation means a control-C will hang until the task completes. You can kill the process but that doesn't give a flushed log (so if you're working remote you might be missing the info for diagnosing).

@safern
Copy link
Member Author

safern commented Feb 27, 2019

I don't think it is the AssemblyResolver, since the AzureDevOpsTask has BaseTask as its base class and it actually enables the AssemblyResolver for the desktop implementation: https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.Helix/Sdk/BaseTask.Desktop.cs#L9

@safern
Copy link
Member Author

safern commented Feb 27, 2019

I'm ok with you undoing the cancellation for now, but it's something you should consider moving forward for tasks which do long running things. Not implementing cancellation means a control-C will hang until the task completes. You can kill the process but that doesn't give a flushed log (so if you're working remote you might be missing the info for diagnosing).

Yeah, makes sense. Maybe moving the ct.ThrowIfCancellationRequested() inside the for loop so for every file it checks and it doesn't download all the files if a cancellation is requested before finishing?

@safern safern merged commit a1b24d2 into dotnet:master Feb 27, 2019
@safern safern deleted the DownloadResultsContainer branch February 27, 2019 17:42
@alexperovich
Copy link
Member

@safern @ericstj #2130 tracks the work to make everything in the helix sdk cancelable. I created it a while back in dotnet/core-eng, but never had time to do it.

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.

5 participants