Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 16cac6d

Browse files
committedMar 17, 2025·
feat: adds mutagen daemon controller
1 parent 449bbd9 commit 16cac6d

17 files changed

+1108
-53
lines changed
 

‎App/App.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,14 @@
6262
</PackageReference>
6363
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.2.0" />
6464
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" />
65+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
66+
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.1" />
6567
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
6668
</ItemGroup>
6769

6870
<ItemGroup>
6971
<ProjectReference Include="..\CoderSdk\CoderSdk.csproj" />
72+
<ProjectReference Include="..\MutagenSdk\MutagenSdk.csproj" />
7073
<ProjectReference Include="..\Vpn.Proto\Vpn.Proto.csproj" />
7174
<ProjectReference Include="..\Vpn\Vpn.csproj" />
7275
</ItemGroup>

‎App/App.xaml.cs

+21-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
using Coder.Desktop.App.ViewModels;
77
using Coder.Desktop.App.Views;
88
using Coder.Desktop.App.Views.Pages;
9+
using Coder.Desktop.Vpn;
10+
using Microsoft.Extensions.Configuration;
911
using Microsoft.Extensions.DependencyInjection;
12+
using Microsoft.Extensions.Hosting;
1013
using Microsoft.UI.Xaml;
14+
using Microsoft.Win32;
1115

1216
namespace Coder.Desktop.App;
1317

@@ -17,12 +21,28 @@ public partial class App : Application
1721

1822
private bool _handleWindowClosed = true;
1923

24+
#if !DEBUG
25+
private const string MutagenControllerConfigSection = "MutagenController";
26+
#else
27+
private const string MutagenControllerConfigSection = "DebugMutagenController";
28+
#endif
29+
2030
public App()
2131
{
22-
var services = new ServiceCollection();
32+
var builder = Host.CreateApplicationBuilder();
33+
34+
(builder.Configuration as IConfigurationBuilder).Add(
35+
new RegistryConfigurationSource(Registry.LocalMachine, @"SOFTWARE\Coder Desktop"));
36+
37+
var services = builder.Services;
38+
2339
services.AddSingleton<ICredentialManager, CredentialManager>();
2440
services.AddSingleton<IRpcController, RpcController>();
2541

42+
services.AddOptions<MutagenControllerConfig>()
43+
.Bind(builder.Configuration.GetSection(MutagenControllerConfigSection));
44+
services.AddSingleton<ISyncSessionController, MutagenController>();
45+
2646
// SignInWindow views and view models
2747
services.AddTransient<SignInViewModel>();
2848
services.AddTransient<SignInWindow>();

‎App/Services/MutagenController.cs

+439
Large diffs are not rendered by default.

‎App/packages.lock.json

+353-2
Large diffs are not rendered by default.

‎CoderSdk/packages.lock.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"version": 1,
33
"dependencies": {
4-
"net8.0": {}
4+
"net8.0": {},
5+
"net8.0/win-x64": {}
56
}
67
}

‎Installer/Program.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,21 @@ private static int BuildMsiPackage(MsiOptions opts)
250250
programFiles64Folder.AddDir(installDir);
251251
project.AddDir(programFiles64Folder);
252252

253-
// Add registry values that are consumed by the manager. Note that these
254-
// should not be changed. See Vpn.Service/Program.cs and
255-
// Vpn.Service/ManagerConfig.cs for more details.
253+
256254
project.AddRegValues(
255+
// Add registry values that are consumed by the manager. Note that these
256+
// should not be changed. See Vpn.Service/Program.cs and
257+
// Vpn.Service/ManagerConfig.cs for more details.
257258
new RegValue(RegistryHive, RegistryKey, "Manager:ServiceRpcPipeName", "Coder.Desktop.Vpn"),
258259
new RegValue(RegistryHive, RegistryKey, "Manager:TunnelBinaryPath",
259260
$"[INSTALLFOLDER]{opts.VpnDir}\\coder-vpn.exe"),
260261
new RegValue(RegistryHive, RegistryKey, "Manager:LogFileLocation",
261262
@"[INSTALLFOLDER]coder-desktop-service.log"),
262263
new RegValue(RegistryHive, RegistryKey, "Manager:TunnelBinarySignatureSigner", "Coder Technologies Inc."),
263-
new RegValue(RegistryHive, RegistryKey, "Manager:TunnelBinaryAllowVersionMismatch", "false"));
264+
new RegValue(RegistryHive, RegistryKey, "Manager:TunnelBinaryAllowVersionMismatch", "false"),
265+
// Add registry values that are consumed by the MutagenController.
266+
new RegValue(RegistryHive, RegistryKey, "MutagenController:MutagenExecutablePath", @"[INSTALLFOLDER]mutagen.exe")
267+
);
264268

265269
// Note: most of this control panel info will not be visible as this
266270
// package is usually hidden in favor of the bootstrapper showing
+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System.Diagnostics;
2+
using System.Runtime.InteropServices;
3+
using Coder.Desktop.App.Services;
4+
5+
namespace Coder.Desktop.Tests.App.Services;
6+
7+
[TestFixture]
8+
public class MutagenControllerTest
9+
{
10+
[OneTimeSetUp]
11+
public async Task DownloadMutagen()
12+
{
13+
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token;
14+
var scriptDirectory = Path.GetFullPath(Path.Combine(TestContext.CurrentContext.TestDirectory,
15+
"..", "..", "..", "..", "scripts"));
16+
var process = new Process();
17+
process.StartInfo.FileName = "powershell.exe";
18+
process.StartInfo.UseShellExecute = false;
19+
process.StartInfo.Arguments = $"-ExecutionPolicy Bypass -File Get-Mutagen.ps1 -arch {_arch}";
20+
process.StartInfo.RedirectStandardError = true;
21+
process.StartInfo.RedirectStandardOutput = true;
22+
process.StartInfo.WorkingDirectory = scriptDirectory;
23+
process.Start();
24+
var output = await process.StandardOutput.ReadToEndAsync(ct);
25+
TestContext.Out.Write(output);
26+
var error = await process.StandardError.ReadToEndAsync(ct);
27+
TestContext.Error.Write(error);
28+
Assert.That(process.ExitCode, Is.EqualTo(0));
29+
_mutagenBinaryPath = Path.Combine(scriptDirectory, "files", $"mutagen-windows-{_arch}.exe");
30+
Assert.That(File.Exists(_mutagenBinaryPath));
31+
}
32+
33+
[SetUp]
34+
public void CreateTempDir()
35+
{
36+
_tempDirectory = Directory.CreateTempSubdirectory(GetType().Name);
37+
TestContext.Out.WriteLine($"temp directory: {_tempDirectory}");
38+
}
39+
40+
private readonly string _arch = RuntimeInformation.ProcessArchitecture switch
41+
{
42+
Architecture.X64 => "x64",
43+
Architecture.Arm64 => "arm64",
44+
// We only support amd64 and arm64 on Windows currently.
45+
_ => throw new PlatformNotSupportedException(
46+
$"Unsupported architecture '{RuntimeInformation.ProcessArchitecture}'. Coder only supports x64 and arm64."),
47+
};
48+
49+
private string _mutagenBinaryPath;
50+
private DirectoryInfo _tempDirectory;
51+
52+
[Test(Description = "Shut down daemon when no sessions")]
53+
[CancelAfter(30_000)]
54+
public async Task ShutdownNoSessions(CancellationToken ct)
55+
{
56+
// NUnit runs each test in a temporary directory
57+
var dataDirectory = _tempDirectory.FullName;
58+
await using var controller = new MutagenController(_mutagenBinaryPath, dataDirectory);
59+
await controller.Initialize(ct);
60+
61+
// log file tells us the daemon was started.
62+
var logPath = Path.Combine(dataDirectory, "daemon.log");
63+
Assert.That(File.Exists(logPath));
64+
65+
var lockPath = Path.Combine(dataDirectory, "daemon", "daemon.lock");
66+
// If we can lock the daemon.lock file, it means the daemon has stopped.
67+
while (true)
68+
{
69+
ct.ThrowIfCancellationRequested();
70+
try
71+
{
72+
await using var lockFile = new FileStream(lockPath, FileMode.Open, FileAccess.Write, FileShare.None);
73+
}
74+
catch (IOException e)
75+
{
76+
TestContext.Out.WriteLine($"Didn't get lock (will retry): {e.Message}");
77+
await Task.Delay(100, ct);
78+
}
79+
80+
break;
81+
}
82+
}
83+
84+
[Test(Description = "Daemon is restarted when we create a session")]
85+
[CancelAfter(30_000)]
86+
public async Task CreateRestartsDaemon(CancellationToken ct)
87+
{
88+
// NUnit runs each test in a temporary directory
89+
var dataDirectory = _tempDirectory.FullName;
90+
await using (var controller = new MutagenController(_mutagenBinaryPath, dataDirectory))
91+
{
92+
await controller.Initialize(ct);
93+
await controller.CreateSyncSession(new SyncSession(), ct);
94+
}
95+
96+
var logPath = Path.Combine(dataDirectory, "daemon.log");
97+
Assert.That(File.Exists(logPath));
98+
var logLines = File.ReadAllLines(logPath);
99+
100+
// Here we're going to use the log to verify the daemon was started 2 times.
101+
// slightly brittle, but unlikely this log line will change.
102+
Assert.That(logLines.Count(s => s.Contains("[sync] Session manager initialized")), Is.EqualTo(2));
103+
}
104+
105+
[Test(Description = "Controller kills orphaned daemon")]
106+
[CancelAfter(30_000)]
107+
public async Task Orphaned(CancellationToken ct)
108+
{
109+
// NUnit runs each test in a temporary directory
110+
var dataDirectory = _tempDirectory.FullName;
111+
MutagenController? controller1 = null;
112+
MutagenController? controller2 = null;
113+
try
114+
{
115+
controller1 = new MutagenController(_mutagenBinaryPath, dataDirectory);
116+
await controller1.Initialize(ct);
117+
await controller1.CreateSyncSession(new SyncSession(), ct);
118+
119+
controller2 = new MutagenController(_mutagenBinaryPath, dataDirectory);
120+
await controller2.Initialize(ct);
121+
}
122+
finally
123+
{
124+
if (controller1 != null) await controller1.DisposeAsync();
125+
if (controller2 != null) await controller2.DisposeAsync();
126+
}
127+
128+
var logPath = Path.Combine(dataDirectory, "daemon.log");
129+
Assert.That(File.Exists(logPath));
130+
var logLines = File.ReadAllLines(logPath);
131+
132+
// Here we're going to use the log to verify the daemon was started 3 times.
133+
// slightly brittle, but unlikely this log line will change.
134+
Assert.That(logLines.Count(s => s.Contains("[sync] Session manager initialized")), Is.EqualTo(3));
135+
}
136+
137+
// TODO: Add more tests once we actually implement creating sessions on the daemon
138+
}

‎Tests.Vpn.Service/packages.lock.json

+1
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@
474474
"type": "Project",
475475
"dependencies": {
476476
"Coder.Desktop.Vpn.Proto": "[1.0.0, )",
477+
"Microsoft.Extensions.Configuration": "[9.0.1, )",
477478
"Semver": "[3.0.0, )",
478479
"System.IO.Pipelines": "[9.0.1, )"
479480
}

‎Tests.Vpn/packages.lock.json

+20-2
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,27 @@
4646
"resolved": "17.12.0",
4747
"contentHash": "4svMznBd5JM21JIG2xZKGNanAHNXplxf/kQDFfLHXQ3OnpJkayRK/TjacFjA+EYmoyuNXHo/sOETEfcYtAzIrA=="
4848
},
49+
"Microsoft.Extensions.Configuration": {
50+
"type": "Transitive",
51+
"resolved": "9.0.1",
52+
"contentHash": "VuthqFS+ju6vT8W4wevdhEFiRi1trvQtkzWLonApfF5USVzzDcTBoY3F24WvN/tffLSrycArVfX1bThm/9xY2A==",
53+
"dependencies": {
54+
"Microsoft.Extensions.Configuration.Abstractions": "9.0.1",
55+
"Microsoft.Extensions.Primitives": "9.0.1"
56+
}
57+
},
58+
"Microsoft.Extensions.Configuration.Abstractions": {
59+
"type": "Transitive",
60+
"resolved": "9.0.1",
61+
"contentHash": "+4hfFIY1UjBCXFTTOd+ojlDPq6mep3h5Vq5SYE3Pjucr7dNXmq4S/6P/LoVnZFz2e/5gWp/om4svUFgznfULcA==",
62+
"dependencies": {
63+
"Microsoft.Extensions.Primitives": "9.0.1"
64+
}
65+
},
4966
"Microsoft.Extensions.Primitives": {
5067
"type": "Transitive",
51-
"resolved": "5.0.1",
52-
"contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
68+
"resolved": "9.0.1",
69+
"contentHash": "bHtTesA4lrSGD1ZUaMIx6frU3wyy0vYtTa/hM6gGQu5QNrydObv8T5COiGUWsisflAfmsaFOe9Xvw5NSO99z0g=="
5370
},
5471
"Microsoft.TestPlatform.ObjectModel": {
5572
"type": "Transitive",
@@ -95,6 +112,7 @@
95112
"type": "Project",
96113
"dependencies": {
97114
"Coder.Desktop.Vpn.Proto": "[1.0.0, )",
115+
"Microsoft.Extensions.Configuration": "[9.0.1, )",
98116
"Semver": "[3.0.0, )",
99117
"System.IO.Pipelines": "[9.0.1, )"
100118
}

‎Vpn.DebugClient/packages.lock.json

+20-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,27 @@
77
"resolved": "3.29.3",
88
"contentHash": "t7nZFFUFwigCwZ+nIXHDLweXvwIpsOXi+P7J7smPT/QjI3EKxnCzTQOhBqyEh6XEzc/pNH+bCFOOSjatrPt6Tw=="
99
},
10+
"Microsoft.Extensions.Configuration": {
11+
"type": "Transitive",
12+
"resolved": "9.0.1",
13+
"contentHash": "VuthqFS+ju6vT8W4wevdhEFiRi1trvQtkzWLonApfF5USVzzDcTBoY3F24WvN/tffLSrycArVfX1bThm/9xY2A==",
14+
"dependencies": {
15+
"Microsoft.Extensions.Configuration.Abstractions": "9.0.1",
16+
"Microsoft.Extensions.Primitives": "9.0.1"
17+
}
18+
},
19+
"Microsoft.Extensions.Configuration.Abstractions": {
20+
"type": "Transitive",
21+
"resolved": "9.0.1",
22+
"contentHash": "+4hfFIY1UjBCXFTTOd+ojlDPq6mep3h5Vq5SYE3Pjucr7dNXmq4S/6P/LoVnZFz2e/5gWp/om4svUFgznfULcA==",
23+
"dependencies": {
24+
"Microsoft.Extensions.Primitives": "9.0.1"
25+
}
26+
},
1027
"Microsoft.Extensions.Primitives": {
1128
"type": "Transitive",
12-
"resolved": "5.0.1",
13-
"contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
29+
"resolved": "9.0.1",
30+
"contentHash": "bHtTesA4lrSGD1ZUaMIx6frU3wyy0vYtTa/hM6gGQu5QNrydObv8T5COiGUWsisflAfmsaFOe9Xvw5NSO99z0g=="
1431
},
1532
"Semver": {
1633
"type": "Transitive",
@@ -29,6 +46,7 @@
2946
"type": "Project",
3047
"dependencies": {
3148
"Coder.Desktop.Vpn.Proto": "[1.0.0, )",
49+
"Microsoft.Extensions.Configuration": "[9.0.1, )",
3250
"Semver": "[3.0.0, )",
3351
"System.IO.Pipelines": "[9.0.1, )"
3452
}

‎Vpn.Proto/packages.lock.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"resolved": "2.69.0",
1515
"contentHash": "W5hW4R1h19FCzKb8ToqIJMI5YxnQqGmREEpV8E5XkfCtLPIK5MSHztwQ8gZUfG8qu9fg5MhItjzyPRqQBjnrbA=="
1616
}
17-
}
17+
},
18+
"net8.0/win-x64": {}
1819
}
1920
}

‎Vpn.Service/packages.lock.json

+27
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@
416416
"type": "Project",
417417
"dependencies": {
418418
"Coder.Desktop.Vpn.Proto": "[1.0.0, )",
419+
"Microsoft.Extensions.Configuration": "[9.0.1, )",
419420
"Semver": "[3.0.0, )",
420421
"System.IO.Pipelines": "[9.0.1, )"
421422
}
@@ -426,6 +427,32 @@
426427
"Google.Protobuf": "[3.29.3, )"
427428
}
428429
}
430+
},
431+
"net8.0-windows7.0/win-x64": {
432+
"Microsoft.Security.Extensions": {
433+
"type": "Direct",
434+
"requested": "[1.3.0, )",
435+
"resolved": "1.3.0",
436+
"contentHash": "xK8WFEo5WMUE8DI8W+GjhRwpVcPrxc4DyTjfxh39+yOyhAtC5TBHDlFEJks5toNZHsUeUuiWELIX25oTWOKPBw=="
437+
},
438+
"System.Diagnostics.EventLog": {
439+
"type": "Transitive",
440+
"resolved": "9.0.1",
441+
"contentHash": "iVnDpgYJsRaRFnk77kcLA3+913WfWDtnAKrQl9tQ5ahqKANTaJKmQdsuPWWiAPWE9pk1Kj4Pg9JGXWfFYYyakQ=="
442+
},
443+
"System.ServiceProcess.ServiceController": {
444+
"type": "Transitive",
445+
"resolved": "9.0.1",
446+
"contentHash": "Ghm4yP29P3cC65Qof8CrgU3WO/q3ERtht6/CrvcUl1FgRs6D7exj75GuG4ciRv0sjygtvyd675924DFsxxnEgA==",
447+
"dependencies": {
448+
"System.Diagnostics.EventLog": "9.0.1"
449+
}
450+
},
451+
"System.Text.Encodings.Web": {
452+
"type": "Transitive",
453+
"resolved": "9.0.1",
454+
"contentHash": "XkspqduP2t1e1x2vBUAD/xZ5ZDvmywuUwsmB93MvyQLospJfqtX0GsR/kU0vUL2h4kmvf777z3txV2W4NrQ9Qg=="
455+
}
429456
}
430457
}
431458
}

‎Vpn.Service/RegistryConfigurationSource.cs ‎Vpn/RegistryConfigurationSource.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Microsoft.Extensions.Configuration;
22
using Microsoft.Win32;
33

4-
namespace Coder.Desktop.Vpn.Service;
4+
namespace Coder.Desktop.Vpn;
55

66
public class RegistryConfigurationSource : IConfigurationSource
77
{

‎Vpn/Vpn.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
</ItemGroup>
1515

1616
<ItemGroup>
17+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.1" />
1718
<PackageReference Include="Semver" Version="3.0.0" />
1819
<PackageReference Include="System.IO.Pipelines" Version="9.0.1" />
1920
</ItemGroup>

‎Vpn/packages.lock.json

+22-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
"version": 1,
33
"dependencies": {
44
"net8.0": {
5+
"Microsoft.Extensions.Configuration": {
6+
"type": "Direct",
7+
"requested": "[9.0.1, )",
8+
"resolved": "9.0.1",
9+
"contentHash": "VuthqFS+ju6vT8W4wevdhEFiRi1trvQtkzWLonApfF5USVzzDcTBoY3F24WvN/tffLSrycArVfX1bThm/9xY2A==",
10+
"dependencies": {
11+
"Microsoft.Extensions.Configuration.Abstractions": "9.0.1",
12+
"Microsoft.Extensions.Primitives": "9.0.1"
13+
}
14+
},
515
"Semver": {
616
"type": "Direct",
717
"requested": "[3.0.0, )",
@@ -22,17 +32,26 @@
2232
"resolved": "3.29.3",
2333
"contentHash": "t7nZFFUFwigCwZ+nIXHDLweXvwIpsOXi+P7J7smPT/QjI3EKxnCzTQOhBqyEh6XEzc/pNH+bCFOOSjatrPt6Tw=="
2434
},
35+
"Microsoft.Extensions.Configuration.Abstractions": {
36+
"type": "Transitive",
37+
"resolved": "9.0.1",
38+
"contentHash": "+4hfFIY1UjBCXFTTOd+ojlDPq6mep3h5Vq5SYE3Pjucr7dNXmq4S/6P/LoVnZFz2e/5gWp/om4svUFgznfULcA==",
39+
"dependencies": {
40+
"Microsoft.Extensions.Primitives": "9.0.1"
41+
}
42+
},
2543
"Microsoft.Extensions.Primitives": {
2644
"type": "Transitive",
27-
"resolved": "5.0.1",
28-
"contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
45+
"resolved": "9.0.1",
46+
"contentHash": "bHtTesA4lrSGD1ZUaMIx6frU3wyy0vYtTa/hM6gGQu5QNrydObv8T5COiGUWsisflAfmsaFOe9Xvw5NSO99z0g=="
2947
},
3048
"Coder.Desktop.Vpn.Proto": {
3149
"type": "Project",
3250
"dependencies": {
3351
"Google.Protobuf": "[3.29.3, )"
3452
}
3553
}
36-
}
54+
},
55+
"net8.0/win-x64": {}
3756
}
3857
}

‎scripts/Get-Mutagen.ps1

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Usage: Get-Mutagen.ps1 -arch <x64|arm64>
2+
param (
3+
[ValidateSet("x64", "arm64")]
4+
[Parameter(Mandatory = $true)]
5+
[string] $arch
6+
)
7+
8+
function Download-File([string] $url, [string] $outputPath, [string] $etagFile) {
9+
Write-Host "Downloading '$url' to '$outputPath'"
10+
# We use `curl.exe` here because `Invoke-WebRequest` is notoriously slow.
11+
& curl.exe `
12+
--progress-bar `
13+
--show-error `
14+
--fail `
15+
--location `
16+
--etag-compare $etagFile `
17+
--etag-save $etagFile `
18+
--output $outputPath `
19+
$url
20+
if ($LASTEXITCODE -ne 0) { throw "Failed to download $url" }
21+
if (!(Test-Path $outputPath) -or (Get-Item $outputPath).Length -eq 0) {
22+
throw "Failed to download '$url', output file '$outputPath' is missing or empty"
23+
}
24+
}
25+
26+
$goArch = switch ($arch) {
27+
"x64" { "amd64" }
28+
"arm64" { "arm64" }
29+
default { throw "Unsupported architecture: $arch" }
30+
}
31+
32+
# Download the mutagen binary from our bucket for this platform if we don't have
33+
# it yet (or it's different).
34+
$mutagenVersion = "v0.18.1"
35+
$mutagenPath = Join-Path $PSScriptRoot "files\mutagen-windows-$($arch).exe"
36+
$mutagenUrl = "https://storage.googleapis.com/coder-desktop/mutagen/$($mutagenVersion)/mutagen-windows-$($goArch).exe"
37+
$mutagenEtagFile = $mutagenPath + ".etag"
38+
Download-File $mutagenUrl $mutagenPath $mutagenEtagFile
39+
40+
# Download mutagen agents tarball.
41+
$mutagenAgentsPath = Join-Path $PSScriptRoot "files\mutagen-agents.tar.gz"
42+
$mutagenAgentsUrl = "https://storage.googleapis.com/coder-desktop/mutagen/$($mutagenVersion)/mutagen-agents.tar.gz"
43+
$mutagenAgentsEtagFile = $mutagenAgentsPath + ".etag"
44+
Download-File $mutagenAgentsUrl $mutagenAgentsPath $mutagenAgentsEtagFile

‎scripts/Publish.ps1

+6-36
Original file line numberDiff line numberDiff line change
@@ -83,30 +83,6 @@ function Add-CoderSignature([string] $path) {
8383
}
8484
}
8585

86-
function Download-File([string] $url, [string] $outputPath, [string] $etagFile) {
87-
Write-Host "Downloading '$url' to '$outputPath'"
88-
# We use `curl.exe` here because `Invoke-WebRequest` is notoriously slow.
89-
& curl.exe `
90-
--progress-bar `
91-
--show-error `
92-
--fail `
93-
--location `
94-
--etag-compare $etagFile `
95-
--etag-save $etagFile `
96-
--output $outputPath `
97-
$url
98-
if ($LASTEXITCODE -ne 0) { throw "Failed to download $url" }
99-
if (!(Test-Path $outputPath) -or (Get-Item $outputPath).Length -eq 0) {
100-
throw "Failed to download '$url', output file '$outputPath' is missing or empty"
101-
}
102-
}
103-
104-
$goArch = switch ($arch) {
105-
"x64" { "amd64" }
106-
"arm64" { "arm64" }
107-
default { throw "Unsupported architecture: $arch" }
108-
}
109-
11086
# CD to the root of the repo
11187
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
11288
Push-Location $repoRoot
@@ -169,21 +145,15 @@ if ($null -eq $wintunDllSrc) {
169145
$wintunDllDest = Join-Path $vpnFilesPath "wintun.dll"
170146
Copy-Item $wintunDllSrc $wintunDllDest
171147

172-
# Download the mutagen binary from our bucket for this platform if we don't have
173-
# it yet (or it's different).
174-
$mutagenVersion = "v0.18.1"
175-
$mutagenSrcPath = Join-Path $repoRoot "scripts\files\mutagen-windows-$($goArch).exe"
176-
$mutagenSrcUrl = "https://storage.googleapis.com/coder-desktop/mutagen/$($mutagenVersion)/mutagen-windows-$($goArch).exe"
177-
$mutagenEtagFile = $mutagenSrcPath + ".etag"
178-
Download-File $mutagenSrcUrl $mutagenSrcPath $mutagenEtagFile
148+
$scriptRoot = Join-Path $repoRoot "scripts"
149+
$getMutagen = Join-Path $scriptRoot "Get-Mutagen.ps1"
150+
& $getMutagen -arch $arch
151+
152+
$mutagenSrcPath = Join-Path $scriptRoot "files\mutagen-windows-$($arch).exe"
179153
$mutagenDestPath = Join-Path $vpnFilesPath "mutagen.exe"
180154
Copy-Item $mutagenSrcPath $mutagenDestPath
181155

182-
# Download mutagen agents tarball.
183-
$mutagenAgentsSrcPath = Join-Path $repoRoot "scripts\files\mutagen-agents.tar.gz"
184-
$mutagenAgentsSrcUrl = "https://storage.googleapis.com/coder-desktop/mutagen/$($mutagenVersion)/mutagen-agents.tar.gz"
185-
$mutagenAgentsEtagFile = $mutagenAgentsSrcPath + ".etag"
186-
Download-File $mutagenAgentsSrcUrl $mutagenAgentsSrcPath $mutagenAgentsEtagFile
156+
$mutagenAgentsSrcPath = Join-Path $scriptRoot "files\mutagen-agents.tar.gz"
187157
$mutagenAgentsDestPath = Join-Path $vpnFilesPath "mutagen-agents.tar.gz"
188158
Copy-Item $mutagenAgentsSrcPath $mutagenAgentsDestPath
189159

0 commit comments

Comments
 (0)
Please sign in to comment.