Skip to content

Commit 7480593

Browse files
Merge branch 'main' into feature/use-shared-adb-runner
2 parents 9f2aabd + 3087ddd commit 7480593

7 files changed

Lines changed: 74 additions & 28 deletions

File tree

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
<BuildOutputDirectory>$(MSBuildThisFileDirectory)bin\$(Configuration)\</BuildOutputDirectory>
1313
<BootstrapOutputDirectory>$(MSBuildThisFileDirectory)bin\Build$(Configuration)\</BootstrapOutputDirectory>
1414
<TestOutputDirectory>$(MSBuildThisFileDirectory)bin\Test$(Configuration)\</TestOutputDirectory>
15-
<BootstrapTasksAssembly>$(BootstrapOutputDirectory)$(TargetFrameworkNETStandard)\Xamarin.Android.Tools.BootstrapTasks.dll</BootstrapTasksAssembly>
16-
<PrepTasksAssembly>$(BootstrapOutputDirectory)$(TargetFrameworkNETStandard)\xa-prep-tasks.dll</PrepTasksAssembly>
15+
<BootstrapTasksAssembly>$(BootstrapOutputDirectory)$(DotNetStableTargetFramework)\Xamarin.Android.Tools.BootstrapTasks.dll</BootstrapTasksAssembly>
16+
<PrepTasksAssembly>$(BootstrapOutputDirectory)$(DotNetStableTargetFramework)\xa-prep-tasks.dll</PrepTasksAssembly>
1717
<DotNetPreviewPath Condition=" '$(DotNetPreviewPath)' == '' ">$(BuildOutputDirectory)dotnet\</DotNetPreviewPath>
1818
<DotNetPreviewTool Condition=" '$(DotNetPreviewTool)' == '' and Exists('$(DotNetPreviewPath)') ">$(DotNetPreviewPath)dotnet</DotNetPreviewTool>
1919
<DotNetPreviewTool Condition=" '$(DotNetPreviewTool)' == '' ">dotnet</DotNetPreviewTool>

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
44

55
<PropertyGroup>
6-
<TargetFramework>$(TargetFrameworkNETStandard)</TargetFramework>
6+
<TargetFramework>$(DotNetStableTargetFramework)</TargetFramework>
77
<LibZipSharpBundleAllNativeLibraries>true</LibZipSharpBundleAllNativeLibraries>
88
<OutputPath>$(BootstrapOutputDirectory)</OutputPath>
99
</PropertyGroup>

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateFrameworkList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ XElement ToFileElement (ITaskItem file)
6565
new XAttribute ("AssemblyName", assemblyName.Name),
6666
new XAttribute ("Version", version),
6767
new XAttribute ("PublicKeyToken", publicKeyToken),
68-
new XAttribute ("ProcessorArchitecture", assemblyName.ProcessorArchitecture.ToString ()));
68+
new XAttribute ("ProcessorArchitecture", "MSIL"));
6969
}
7070

7171
static string Nullable (string value) => string.IsNullOrEmpty (value) ? null : value;

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateSupportedPlatforms.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ static AndroidVersion ToAndroidVersion (ITaskItem item)
138138
</AndroidApiInfo>
139139
*/
140140

141-
Version.TryParse (item.GetMetadata ("VersionCodeFull"), out var versionCodeFull);
141+
if (!Version.TryParse (item.GetMetadata ("VersionCodeFull"), out var versionCodeFull)) {
142+
throw new ArgumentException ($"Invalid VersionCodeFull '{item.GetMetadata ("VersionCodeFull")}' for item '{item.ItemSpec}'");
143+
}
142144
bool.TryParse (item.GetMetadata ("Stable"), out bool stable);
143145

144146
return new AndroidVersion (versionCodeFull, item.ItemSpec.TrimStart ('v'), item.GetMetadata ("Name"), item.GetMetadata ("Id"), stable);

build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/DownloadUri.cs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using System.Linq;
44
using System.Net.Http;
5+
using System.Security.Cryptography.X509Certificates;
56
using System.Threading;
67
using System.Threading.Tasks;
78

@@ -15,6 +16,13 @@ namespace Xamarin.Android.BuildTools.PrepTasks {
1516

1617
public class DownloadUri : MTask, ICancelableTask
1718
{
19+
const int DefaultMaxRetries = 3;
20+
static readonly TimeSpan[] RetryDelays = {
21+
TimeSpan.FromSeconds (5),
22+
TimeSpan.FromSeconds (15),
23+
TimeSpan.FromSeconds (30),
24+
};
25+
1826
public DownloadUri ()
1927
{
2028
}
@@ -27,6 +35,8 @@ public DownloadUri ()
2735

2836
public string HashHeader { get; set; }
2937

38+
public int MaxRetries { get; set; } = DefaultMaxRetries;
39+
3040
CancellationTokenSource cancellationTokenSource;
3141

3242
public void Cancel ()
@@ -44,13 +54,18 @@ public override bool Execute ()
4454
var source = cancellationTokenSource = new CancellationTokenSource ();
4555
var tasks = new Task<ITaskItem> [SourceUris.Length];
4656

47-
// LGTM recommendation
48-
//
49-
// Using HttpClient without providing a platform specific handler (WinHttpHandler or CurlHandler) where the CheckCertificateRevocationList property is set
50-
// to true, will allow revoked certificates to be accepted by the HttpClient as valid.
51-
//
52-
var handler = new HttpClientHandler {
53-
CheckCertificateRevocationList = true,
57+
// Configure cert revocation checking in a fail-open state to avoid intermittent
58+
// failures on macOS when the CRL/OCSP endpoint is unreachable.
59+
// Matches the approach in dotnet/arcade's DownloadFile task:
60+
// https://github.com/dotnet/arcade/blob/a07b621/src/Microsoft.DotNet.Arcade.Sdk/src/DownloadFile.cs#L122-L145
61+
var handler = new SocketsHttpHandler ();
62+
handler.SslOptions.CertificateChainPolicy = new X509ChainPolicy {
63+
RevocationMode = X509RevocationMode.Online,
64+
RevocationFlag = X509RevocationFlag.ExcludeRoot,
65+
VerificationFlags =
66+
X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown |
67+
X509VerificationFlags.IgnoreEndRevocationUnknown,
68+
VerificationTimeIgnored = true,
5469
};
5570

5671
using (var client = new HttpClient (handler)) {
@@ -89,21 +104,39 @@ async Task<ITaskItem> DownloadFile (HttpClient client, CancellationTokenSource s
89104
var tempPath = Path.Combine (dp, "." + dn + ".download");
90105
Directory.CreateDirectory(dp);
91106

92-
Log.LogMessage (MessageImportance.Normal, $"Downloading `{uri}` to `{tempPath}`.");
93-
try {
94-
using (var r = await client.GetAsync (uri, HttpCompletionOption.ResponseHeadersRead, source.Token)) {
95-
r.EnsureSuccessStatusCode ();
96-
using (var s = await r.Content.ReadAsStreamAsync ())
97-
using (var o = File.OpenWrite (tempPath)) {
98-
await s.CopyToAsync (o, 4096, source.Token);
107+
int retries = Math.Max (0, MaxRetries);
108+
for (int attempt = 0; attempt <= retries; attempt++) {
109+
Log.LogMessage (MessageImportance.Normal, $"Downloading `{uri}` to `{tempPath}` (attempt {attempt + 1} of {retries + 1}).");
110+
try {
111+
using (var r = await client.GetAsync (uri, HttpCompletionOption.ResponseHeadersRead, source.Token)) {
112+
r.EnsureSuccessStatusCode ();
113+
using (var s = await r.Content.ReadAsStreamAsync ())
114+
using (var o = File.Create (tempPath)) {
115+
await s.CopyToAsync (o, 4096, source.Token);
116+
}
99117
}
118+
Log.LogMessage (MessageImportance.Low, $"mv '{tempPath}' '{destinationFile}'.");
119+
File.Move (tempPath, destinationFile.ItemSpec);
120+
return destinationFile;
121+
}
122+
catch (Exception e) when (attempt < retries && !source.IsCancellationRequested) {
123+
var delay = attempt < RetryDelays.Length ? RetryDelays [attempt] : RetryDelays [RetryDelays.Length - 1];
124+
Log.LogWarning ("Failed to download URL `{0}` (attempt {1} of {2}): {3}. Retrying in {4} seconds.",
125+
uri, attempt + 1, retries + 1, e.Message, (int) delay.TotalSeconds);
126+
try {
127+
File.Delete (tempPath);
128+
} catch {
129+
}
130+
try {
131+
await TTask.Delay (delay, source.Token);
132+
} catch (OperationCanceledException) {
133+
break;
134+
}
135+
}
136+
catch (Exception e) {
137+
Log.LogError ("Unable to download URL `{0}` to `{1}`: {2}", uri, destinationFile, e.Message);
138+
Log.LogErrorFromException (e);
100139
}
101-
Log.LogMessage (MessageImportance.Low, $"mv '{tempPath}' '{destinationFile}'.");
102-
File.Move (tempPath, destinationFile.ItemSpec);
103-
}
104-
catch (Exception e) {
105-
Log.LogError ("Unable to download URL `{0}` to `{1}`: {2}", uri, destinationFile, e.Message);
106-
Log.LogErrorFromException (e);
107140
}
108141
return destinationFile;
109142
}

build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/HashFileContents.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void ProcessFiles ()
5656
{
5757
var hashes = new List<TaskItem> (Files.Length);
5858
byte[] block = new byte [4096];
59-
using (var complete = System.Security.Cryptography.HashAlgorithm.Create (HashAlgorithm)) {
59+
using (var complete = CreateHashAlgorithm (HashAlgorithm)) {
6060
foreach (var file in Files) {
6161
var hash = ProcessFile (complete, block, file.ItemSpec);
6262
var e = new TaskItem (hash);
@@ -87,7 +87,7 @@ string ProcessFile (HashAlgorithm complete, byte[] block, string path)
8787
}
8888
memoryStream.Seek (0, SeekOrigin.Begin);
8989

90-
using (var fileHash = System.Security.Cryptography.HashAlgorithm.Create (HashAlgorithm)) {
90+
using (var fileHash = CreateHashAlgorithm (HashAlgorithm)) {
9191
int read;
9292
while ((read = memoryStream.Read (block, 0, block.Length)) > 0) {
9393
complete.TransformBlock (block, 0, read, block, 0);
@@ -103,6 +103,17 @@ string FormatHash (byte[] hash)
103103
{
104104
return string.Join ("", hash.Select (b => b.ToString ("x2")));
105105
}
106+
107+
#pragma warning disable CA5350 // used for content hashing, not security
108+
static System.Security.Cryptography.HashAlgorithm CreateHashAlgorithm (string name) =>
109+
name.ToUpperInvariant () switch {
110+
"SHA1" => SHA1.Create (),
111+
"SHA256" => SHA256.Create (),
112+
"SHA384" => SHA384.Create (),
113+
"SHA512" => SHA512.Create (),
114+
_ => throw new NotSupportedException ($"Hash algorithm '{name}' is not supported."),
115+
};
116+
#pragma warning restore CA5350
106117
}
107118
}
108119

build-tools/xa-prep-tasks/xa-prep-tasks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>$(TargetFrameworkNETStandard)</TargetFramework>
4+
<TargetFramework>$(DotNetStableTargetFramework)</TargetFramework>
55
<RootNamespace>Xamarin.Android.BuildTools.PrepTasks</RootNamespace>
66
<OutputPath>$(BootstrapOutputDirectory)</OutputPath>
77
</PropertyGroup>

0 commit comments

Comments
 (0)