forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGenerateBundle.cs
More file actions
133 lines (116 loc) · 5.9 KB
/
GenerateBundle.cs
File metadata and controls
133 lines (116 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Build.Framework;
using Microsoft.NET.HostModel.Bundle;
namespace Microsoft.NET.Build.Tasks
{
public class GenerateBundle : TaskBase, ICancelableTask
{
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private readonly Random _jitter =
#if NET
Random.Shared;
#else
new Random();
#endif
[Required]
public ITaskItem[] FilesToBundle { get; set; } = null!;
[Required]
public string AppHostName { get; set; } = null!;
[Required]
public bool IncludeSymbols { get; set; }
[Required]
public bool IncludeNativeLibraries { get; set; }
[Required]
public bool IncludeAllContent { get; set; }
[Required]
public string TargetFrameworkVersion { get; set; } = null!;
[Required]
public string RuntimeIdentifier { get; set; } = null!;
[Required]
public string OutputDir { get; set; } = null!;
[Required]
public bool ShowDiagnosticOutput { get; set; }
[Required]
public bool EnableCompressionInSingleFile { get; set; }
public bool EnableMacOsCodeSign { get; set; } = true;
[Output]
public ITaskItem[] ExcludedFiles { get; set; } = null!;
public int? RetryCount { get; set; } = 3;
public void Cancel() => _cancellationTokenSource.Cancel();
protected override void ExecuteCore()
{
ExecuteWithRetry().GetAwaiter().GetResult();
}
private async Task ExecuteWithRetry()
{
OSPlatform targetOS = RuntimeIdentifier.StartsWith("win") ? OSPlatform.Windows :
RuntimeIdentifier.StartsWith("osx") ? OSPlatform.OSX :
RuntimeIdentifier.StartsWith("freebsd") ? OSPlatform.Create("FREEBSD") :
RuntimeIdentifier.StartsWith("illumos") ? OSPlatform.Create("ILLUMOS") :
RuntimeIdentifier.StartsWith("haiku") ? OSPlatform.Create("HAIKU") :
OSPlatform.Linux;
Architecture targetArch = RuntimeIdentifier.EndsWith("-x64") || RuntimeIdentifier.Contains("-x64-") ? Architecture.X64 :
RuntimeIdentifier.EndsWith("-x86") || RuntimeIdentifier.Contains("-x86-") ? Architecture.X86 :
RuntimeIdentifier.EndsWith("-arm64") || RuntimeIdentifier.Contains("-arm64-") ? Architecture.Arm64 :
RuntimeIdentifier.EndsWith("-arm") || RuntimeIdentifier.Contains("-arm-") ? Architecture.Arm :
#if !NETFRAMEWORK
RuntimeIdentifier.EndsWith("-riscv64") || RuntimeIdentifier.Contains("-riscv64-") ? Architecture.RiscV64 :
RuntimeIdentifier.EndsWith("-loongarch64") || RuntimeIdentifier.Contains("-loongarch64-") ? Architecture.LoongArch64 :
#endif
throw new ArgumentException(nameof(RuntimeIdentifier));
BundleOptions options = BundleOptions.None;
options |= IncludeNativeLibraries ? BundleOptions.BundleNativeBinaries : BundleOptions.None;
options |= IncludeAllContent ? BundleOptions.BundleAllContent : BundleOptions.None;
options |= IncludeSymbols ? BundleOptions.BundleSymbolFiles : BundleOptions.None;
options |= EnableCompressionInSingleFile ? BundleOptions.EnableCompression : BundleOptions.None;
Version version = new(TargetFrameworkVersion);
var bundler = new Bundler(
AppHostName,
OutputDir,
options,
targetOS,
targetArch,
version,
ShowDiagnosticOutput,
macosCodesign: EnableMacOsCodeSign);
var fileSpec = new List<FileSpec>(FilesToBundle.Length);
foreach (var item in FilesToBundle)
{
fileSpec.Add(new FileSpec(sourcePath: item.ItemSpec,
bundleRelativePath: item.GetMetadata(MetadataKeys.RelativePath)));
}
// GenerateBundle has been throwing IOException intermittently in CI runs when accessing the singlefilehost binary specifically.
// We hope that it's a Defender issue and that a quick retry will paper over the intermittent delay.
await DoWithRetry(() => bundler.GenerateBundle(fileSpec));
// Certain files are excluded from the bundle, based on BundleOptions.
// For example:
// Native files and contents files are excluded by default.
// hostfxr and hostpolicy are excluded until singlefilehost is available.
// Return the set of excluded files in ExcludedFiles, so that they can be placed in the publish directory.
ExcludedFiles = FilesToBundle.Zip(fileSpec, (item, spec) => (spec.Excluded) ? item : null).Where(x => x != null).ToArray()!;
}
public async Task DoWithRetry(Action action)
{
bool triedOnce = false;
while (RetryCount > 0 || !triedOnce)
{
if (_cancellationTokenSource.IsCancellationRequested)
{
break;
}
try
{
action();
break;
}
catch (IOException) when (RetryCount > 0)
{
Log.LogMessage(MessageImportance.High, $"Unable to access file during bundling. Retrying {RetryCount} more times...");
RetryCount--;
await Task.Delay(_jitter.Next(10, 50));
}
}
}
}
}