public override Task <RevisionDescription?> RunUpdateAsync(string?currentVersion, string binPath, CancellationToken cancel = default) { if (currentVersion == _specificConfiguration.CurrentVersion) { return(Task.FromResult <RevisionDescription?>(null)); } var binariesPath = Path.Combine(_serverInstance.InstanceDir, "binaries"); if (!Directory.Exists(binariesPath)) { throw new InvalidOperationException( "Expected binaries/ directory containing all client binaries in the instance folder."); } var binariesRoot = new Uri(new Uri(_configuration["BaseUrl"]), $"instances/{_serverInstance.Key}/binaries/"); DownloadInfoPair?GetInfoPair(string platform) { var fileName = GetBuildFilename(platform); var diskFileName = Path.Combine(binariesPath, fileName); if (!File.Exists(diskFileName)) { return(null); } var download = new Uri(binariesRoot, fileName); var hash = GetFileHash(diskFileName); _logger.LogTrace("SHA256 hash for {fileName} is {hash}", fileName, hash); return(new DownloadInfoPair(download.ToString(), hash)); } var revisionDescription = new RevisionDescription( _specificConfiguration.CurrentVersion, GetInfoPair(PlatformNameWindows), GetInfoPair(PlatformNameLinux), GetInfoPair(PlatformNameMacOS)); // ReSharper disable once RedundantTypeArgumentsOfMethod return(Task.FromResult <RevisionDescription?>(revisionDescription)); }
public override async Task <RevisionDescription?> RunUpdateAsync(string?currentVersion, string binPath, CancellationToken cancel = default) { try { _logger.LogTrace("Updating..."); var buildRef = await GetLastSuccessfulBuildAsync(cancel); if (buildRef == null) { _logger.LogTrace("No last build?"); return(null); } if (buildRef.Number.ToString(CultureInfo.InvariantCulture) == currentVersion) { _logger.LogTrace("Update not necessary!"); return(null); } _logger.LogTrace("New version is {newVersion} from {oldVersion}", buildRef.Number, currentVersion ?? "<none>"); var downloadRootUri = new Uri($"{_baseUrl}/job/{_jobName}/{buildRef.Number}/artifact/release/"); async Task <string> GetHash(string platform) { var url = new Uri(downloadRootUri, $"{GetBuildFilename(platform)}.sha256"); var resp = await _httpClient.GetAsync(url, cancel); resp.EnsureSuccessStatusCode(); return((await resp.Content.ReadAsStringAsync()).Trim()); } Uri PlatformUrl(string platform) { return(new Uri(downloadRootUri, Uri.EscapeUriString(GetBuildFilename(platform)))); } async Task <DownloadInfoPair> PlatformInfo(string platform) { var download = PlatformUrl(platform).ToString(); var hash = await GetHash(platform); return(new DownloadInfoPair(download, hash)); } _logger.LogTrace("Fetching revision information from Jenkins..."); // Get revision information that the server instance needs. var revision = new RevisionDescription(buildRef.Number.ToString(CultureInfo.InvariantCulture), await PlatformInfo(PlatformNameWindows), await PlatformInfo(PlatformNameLinux), await PlatformInfo(PlatformNameMacOS)); // Create temporary file to download binary into (not doing this in memory). await using var tempFile = File.Open(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite); // Download URI for server binary. var serverDownload = new Uri(downloadRootUri, $"SS14.Server_{GetHostPlatformName()}_x64.zip"); _logger.LogTrace("Downloading server binary from {download} to {tempFile}", serverDownload, tempFile.Name); // Download to file... var resp = await _httpClient.GetAsync(serverDownload, cancel); await resp.Content.CopyToAsync(tempFile); _logger.LogTrace("Deleting old bin directory ({binPath})", binPath); if (Directory.Exists(binPath)) { Directory.Delete(binPath, true); } Directory.CreateDirectory(binPath); _logger.LogTrace("Extracting zip file"); // Reset file position so we can extract. tempFile.Seek(0, SeekOrigin.Begin); // Actually extract. using var archive = new ZipArchive(tempFile, ZipArchiveMode.Read); archive.ExtractToDirectory(binPath); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // chmod +x Robust.Server var rsPath = Path.Combine(binPath, "Robust.Server"); if (File.Exists(rsPath)) { var proc = Process.Start(new ProcessStartInfo("chmod") { ArgumentList = { "+x", rsPath } }); await proc.WaitForExitAsync(cancel); } } return(revision); } catch (Exception e) { _logger.LogError(e, "Failed to run update!"); return(null); } }