From 64abc61893d333527115ea91b5e94a099b1d43e6 Mon Sep 17 00:00:00 2001 From: junglebus Date: Tue, 15 Oct 2019 04:51:33 +1100 Subject: [PATCH] Update to .NET Core 3.0 (#6151) * Update to .NET Core 3.0 Updated Jackett so that it runs on .NET Core 3.0 now .NET Core 3.0 brings the following benefits https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/ One of the benefits is the ability to create single file executables. I haven't enabled this yet, but its only a one line change to turn it on (would likely also require some changes to the updater). This means that builds for LinuxAMDx64, LinuxARM32, LinuxARM64 and macOS will now run on .NET Core 3.0 instead of 2.2. Windows and Mono remain on full framework. Once .NET Core 3.1 is released (November) I'll look to moving Windows over to .NET Core as well Tested on -Windows 10 x64 -Debian running Jackett with Mono -Debian running Jackett standalone (.NET Core) --- README.md | 12 +-- appveyor.yml | 8 +- build.cake | 90 ++++++++++++++----- src/Jackett.Common/Jackett.Common.csproj | 18 ++-- src/Jackett.Server/Helper.cs | 10 ++- src/Jackett.Server/Jackett.Server.csproj | 39 ++++---- .../Services/FilePermissionService.cs | 4 +- src/Jackett.Server/Startup.cs | 68 +++++++++++++- src/Jackett.Test/Jackett.Test.csproj | 14 +-- src/Jackett.Test/WebUtilityHelpersTests.cs | 2 +- src/Jackett.Tray/Jackett.Tray.csproj | 2 +- src/Jackett.Updater/Jackett.Updater.csproj | 2 +- 12 files changed, 189 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index d1f95f641..2bc04673a 100644 --- a/README.md +++ b/README.md @@ -610,7 +610,7 @@ All contributions are welcome just send a pull request. * Install the .NET Core [SDK](https://www.microsoft.com/net/download/windows) * Clone Jackett * Open Powershell and from the `src` directory, run `dotnet restore` -* Open the Jackett solution in Visual Studio 2017 (version 15.9 or above) +* Open the Jackett solution in Visual Studio 2019 (version 16.3 or above) * Right click on the Jackett solution and click 'Rebuild Solution' to restore nuget packages * Select Jackett.Server as startup project * In the drop down menu of the run button select "Jackett.Server" instead of "IIS Express" @@ -627,21 +627,21 @@ git clone https://github.com/Jackett/Jackett.git cd Jackett/src # dotnet core version -dotnet publish Jackett.Server -f netcoreapp2.2 --self-contained -r osx-x64 -c Debug # takes care of everything -./Jackett.Server/bin/Debug/netcoreapp2.2/osx-x64/jackett # run jackett +dotnet publish Jackett.Server -f netcoreapp3.0 --self-contained -r osx-x64 -c Debug # takes care of everything +./Jackett.Server/bin/Debug/netcoreapp3.0/osx-x64/jackett # run jackett ``` ### Linux ```bash -sudo apt install mono-complete nuget msbuild dotnet-sdk-2.2 # install build tools (debian/ubuntu) +sudo apt install mono-complete nuget msbuild dotnet-sdk-3.0 # install build tools (debian/ubuntu) git clone https://github.com/Jackett/Jackett.git cd Jackett/src # dotnet core version -dotnet publish Jackett.Server -f netcoreapp2.2 --self-contained -r linux-x64 -c Debug # takes care of everything -./Jackett.Server/bin/Debug/netcoreapp2.2/linux-x64/jackett # run jackett +dotnet publish Jackett.Server -f netcoreapp3.0 --self-contained -r linux-x64 -c Debug # takes care of everything +./Jackett.Server/bin/Debug/netcoreapp3.0/linux-x64/jackett # run jackett ``` ## Screenshots diff --git a/appveyor.yml b/appveyor.yml index 15c3265a7..b06ac0abe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +1,11 @@ -version: 0.11.{build} +version: 0.12.{build} skip_tags: true image: - Ubuntu - - Visual Studio 2017 + - Visual Studio 2019 environment: APPVEYOR_YML_DISABLE_PS_LINUX: true configuration: Release -install: - #Remove once .NET Core 2.2.5 is deployed to Appveyor - - sh: sudo apt-get update - - sh: sudo apt-get -y install dotnet-sdk-2.2 assembly_info: patch: true file: '**\AssemblyInfo.*' diff --git a/build.cake b/build.cake index 81c89d0da..cc7661901 100644 --- a/build.cake +++ b/build.cake @@ -16,7 +16,7 @@ var configuration = Argument("configuration", "Debug"); var workingDir = MakeAbsolute(Directory("./")); string artifactsDirName = "Artifacts"; string testResultsDirName = "TestResults"; -string netCoreFramework = "netcoreapp2.2"; +string netCoreFramework = "netcoreapp3.0"; string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj"; string updaterProjectPath = "./src/Jackett.Updater/Jackett.Updater.csproj"; @@ -28,7 +28,7 @@ Task("Info") .Does(() => { Information(@"Jackett Cake build script starting..."); - Information(@"Requires InnoSetup and C:\cygwin to be present for packaging (Pre-installed on AppVeyor) on Windows"); + Information(@"Requires InnoSetup and C:\msys64 to be present for packaging (Pre-installed on AppVeyor) on Windows"); Information(@"Working directory is: " + workingDir); if (IsRunningOnWindows()) @@ -64,7 +64,7 @@ Task("Build-Full-Framework") var buildSettings = new MSBuildSettings() .SetConfiguration(configuration) - .UseToolVersion(MSBuildToolVersion.VS2017); + .UseToolVersion(MSBuildToolVersion.VS2019); MSBuild("./src/Jackett.sln", buildSettings); }); @@ -106,6 +106,8 @@ Task("Package-Windows-Full-Framework") InnoSetupSettings settings = new InnoSetupSettings(); settings.OutputDirectory = workingDir + "/" + artifactsDirName; + //Can remove below line once Cake is updated for InnoSetup 6 - https://github.com/cake-build/cake/pull/2565 + settings.ToolPath = @"C:\Program Files (x86)\Inno Setup 6\ISCC.exe"; settings.Defines = new Dictionary { { "MyFileForVersion", sourceFolder + "/Jackett.Common.dll" }, @@ -145,6 +147,7 @@ Task("Package-Mono-Full-Framework") DeleteFile(buildOutputPath + "/System.Runtime.InteropServices.RuntimeInformation.dll"); + InstallMsysTar(); Gzip("./BuildOutput/net461/linux-x64", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz"); }); @@ -326,13 +329,13 @@ Task("Linux-Environment") }); -private void RunCygwinCommand(string utility, string utilityArguments) +private void RunMsysCommand(string utility, string utilityArguments) { - var cygwinDir = @"C:\cygwin\bin\"; - var utilityProcess = cygwinDir + utility + ".exe"; + var msysDir = @"C:\msys64\usr\bin\"; + var utilityProcess = msysDir + utility + ".exe"; - Information("CygWin Utility: " + utility); - Information("CygWin Directory: " + cygwinDir); + Information("MSYS2 Utility: " + utility); + Information("MSYS2 Directory: " + msysDir); Information("Utility Location: " + utilityProcess); Information("Utility Arguments: " + utilityArguments); @@ -343,7 +346,7 @@ private void RunCygwinCommand(string utility, string utilityArguments) utilityProcess, new ProcessSettings { Arguments = utilityArguments, - WorkingDirectory = cygwinDir, + WorkingDirectory = msysDir, RedirectStandardOutput = true }, out redirectedStandardOutput, @@ -364,11 +367,9 @@ private void RunCygwinCommand(string utility, string utilityArguments) Information(utility + " Exit code: {0}", exitCodeWithArgument); } -private string RelativeWinPathToCygPath(string relativePath) +private string RelativeWinPathToFullPath(string relativePath) { - var cygdriveBase = "/cygdrive/" + workingDir.ToString().Replace(":", "").Replace("\\", "/"); - var cygPath = cygdriveBase + relativePath.TrimStart('.'); - return cygPath; + return (workingDir + relativePath.TrimStart('.')); } private void RunLinuxCommand(string file, string arg) @@ -390,12 +391,12 @@ private void Gzip(string sourceFolder, string outputDirectory, string tarCdirect if (IsRunningOnWindows()) { - var cygSourcePath = RelativeWinPathToCygPath(sourceFolder); - var tarArguments = @"-cvf " + cygSourcePath + "/" + tarFileName + " -C " + cygSourcePath + $" {tarCdirectoryOption} --mode ='755'"; - var gzipArguments = @"-k " + cygSourcePath + "/" + tarFileName; + var fullSourcePath = RelativeWinPathToFullPath(sourceFolder); + var tarArguments = @"--force-local -cvf " + fullSourcePath + "/" + tarFileName + " -C " + fullSourcePath + $" {tarCdirectoryOption} --mode ='755'"; + var gzipArguments = @"-k " + fullSourcePath + "/" + tarFileName; - RunCygwinCommand("Tar", tarArguments); - RunCygwinCommand("Gzip", gzipArguments); + RunMsysCommand("tar", tarArguments); + RunMsysCommand("gzip", gzipArguments); MoveFile($"{sourceFolder}/{tarFileName}.gz", $"{outputDirectory}/{tarFileName}.gz"); } else @@ -421,16 +422,57 @@ private void Gzip(string sourceFolder, string outputDirectory, string tarCdirect } } -private void DotNetCorePublish(string projectPath, string framework, string runtime, string outputPath) +private void InstallMsysTar() { - var settings = new DotNetCorePublishSettings + //Gzip is included by default with MSYS2, but not tar. Use the package manager to install tar + + var startInfo = new System.Diagnostics.ProcessStartInfo() { - Framework = framework, - Runtime = runtime, - OutputDirectory = outputPath + Arguments = "-S --noconfirm tar", + FileName = @"C:\msys64\usr\bin\pacman.exe", + UseShellExecute = false }; - DotNetCorePublish(projectPath, settings); + var process = System.Diagnostics.Process.Start(startInfo); + process.WaitForExit(); + + if (FileExists(@"C:\msys64\usr\bin\tar.exe") && FileExists(@"C:\msys64\usr\bin\gzip.exe")) + { + Information("tar.exe and gzip.exe were found"); + } + else + { + throw new Exception("tar.exe and gzip.exe were NOT found"); + } +} + +private void DotNetCorePublish(string projectPath, string framework, string runtime, string outputPath) +{ + bool publishSingleFile = false; + + if (publishSingleFile && framework != "net461") + { + var settings = new DotNetCorePublishSettings + { + Framework = framework, + Runtime = runtime, + OutputDirectory = outputPath, + ArgumentCustomization = args=>args.Append("/p:PublishSingleFile=true") + }; + + DotNetCorePublish(projectPath, settings); + } + else + { + var settings = new DotNetCorePublishSettings + { + Framework = framework, + Runtime = runtime, + OutputDirectory = outputPath + }; + + DotNetCorePublish(projectPath, settings); + } } ////////////////////////////////////////////////////////////////////// diff --git a/src/Jackett.Common/Jackett.Common.csproj b/src/Jackett.Common/Jackett.Common.csproj index 494e84be2..31da76e75 100644 --- a/src/Jackett.Common/Jackett.Common.csproj +++ b/src/Jackett.Common/Jackett.Common.csproj @@ -7,23 +7,23 @@ - - + + - + - - + + - - - - + + + + diff --git a/src/Jackett.Server/Helper.cs b/src/Jackett.Server/Helper.cs index 7c4f817b8..6cc75bbca 100644 --- a/src/Jackett.Server/Helper.cs +++ b/src/Jackett.Server/Helper.cs @@ -8,15 +8,23 @@ using Microsoft.AspNetCore.Hosting; using NLog; using System.Linq; using System.Text; +#if !NET461 +using Microsoft.Extensions.Hosting; +#endif namespace Jackett.Server { public static class Helper { public static IContainer ApplicationContainer { get; set; } - public static IApplicationLifetime applicationLifetime; private static bool _automapperInitialised = false; +#if NET461 + public static IApplicationLifetime applicationLifetime; +#else + public static IHostApplicationLifetime applicationLifetime; +#endif + public static void Initialize() { if (_automapperInitialised == false) diff --git a/src/Jackett.Server/Jackett.Server.csproj b/src/Jackett.Server/Jackett.Server.csproj index 8244c9e78..aaadb1026 100644 --- a/src/Jackett.Server/Jackett.Server.csproj +++ b/src/Jackett.Server/Jackett.Server.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2;net461 + netcoreapp3.0;net461 jackett.ico JackettConsole Exe @@ -13,25 +13,15 @@ jackett - - win-x86;osx-x64;linux-x64;linux-arm;linux-arm64 - - - - win7-x86;linux-x64 - - - - + + - + + - - - - - + + @@ -39,11 +29,18 @@ + + + + + + + - - - - + + + + diff --git a/src/Jackett.Server/Services/FilePermissionService.cs b/src/Jackett.Server/Services/FilePermissionService.cs index 3b5ee07a5..7cf9884fc 100644 --- a/src/Jackett.Server/Services/FilePermissionService.cs +++ b/src/Jackett.Server/Services/FilePermissionService.cs @@ -1,7 +1,7 @@ using Jackett.Common.Services.Interfaces; using NLog; using System; -#if NETCOREAPP2_2 +#if !NET461 using Mono.Unix; #endif @@ -18,7 +18,7 @@ namespace Jackett.Server.Services public void MakeFileExecutable(string path) { -#if NETCOREAPP2_2 +#if !NET461 //Calling the file permission service to limit usage to netcoreapp. The Mono.Posix.NETStandard library causes issues outside of .NET Core //https://github.com/xamarin/XamarinComponents/issues/282 diff --git a/src/Jackett.Server/Startup.cs b/src/Jackett.Server/Startup.cs index 52b6259e6..a85292a81 100644 --- a/src/Jackett.Server/Startup.cs +++ b/src/Jackett.Server/Startup.cs @@ -21,6 +21,9 @@ using Newtonsoft.Json.Serialization; using System; using System.IO; using System.Text; +#if !NET461 +using Microsoft.Extensions.Hosting; +#endif namespace Jackett.Server { @@ -49,6 +52,9 @@ namespace Jackett.Server options.Cookie.SameSite = SameSiteMode.None; }); + + +#if NET461 services.AddMvc(config => { var policy = new AuthorizationPolicyBuilder() @@ -59,8 +65,20 @@ namespace Jackett.Server .AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //Web app uses Pascal Case JSON + }); +#else + services.AddControllers(config => + { + var policy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); + config.Filters.Add(new AuthorizeFilter(policy)); }) - .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + .AddNewtonsoftJson(options => + { + options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //Web app uses Pascal Case JSON + }); +#endif RuntimeSettings runtimeSettings = new RuntimeSettings(); Configuration.GetSection("RuntimeSettings").Bind(runtimeSettings); @@ -96,6 +114,7 @@ namespace Jackett.Server } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. +#if NET461 public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime) { applicationLifetime.ApplicationStopping.Register(OnShutdown); @@ -134,6 +153,53 @@ namespace Jackett.Server app.UseMvc(); } +#else + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime) + { + applicationLifetime.ApplicationStopping.Register(OnShutdown); + Helper.applicationLifetime = applicationLifetime; + app.UseResponseCompression(); + + app.UseDeveloperExceptionPage(); + + app.UseCustomExceptionHandler(); + + string serverBasePath = Helper.ServerService.BasePath() ?? string.Empty; + + if (!string.IsNullOrEmpty(serverBasePath)) + { + app.UsePathBase(serverBasePath); + } + + app.UseForwardedHeaders(new ForwardedHeadersOptions + { + // When adjusting these pareamters make sure it's well tested with various environments + // See https://github.com/Jackett/Jackett/issues/3517 + ForwardLimit = 10, + ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost + }); + + var rewriteOptions = new RewriteOptions() + .AddRewrite(@"^torznab\/([\w-]*)", "api/v2.0/indexers/$1/results/torznab", skipRemainingRules: true) //legacy torznab route + .AddRewrite(@"^potato\/([\w-]*)", "api/v2.0/indexers/$1/results/potato", skipRemainingRules: true) //legacy potato route + .Add(RedirectRules.RedirectToDashboard); + + app.UseRewriter(rewriteOptions); + + app.UseStaticFiles(); + + app.UseAuthentication(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } +#endif + + private void OnShutdown() { diff --git a/src/Jackett.Test/Jackett.Test.csproj b/src/Jackett.Test/Jackett.Test.csproj index e9a02742f..1c409aa23 100644 --- a/src/Jackett.Test/Jackett.Test.csproj +++ b/src/Jackett.Test/Jackett.Test.csproj @@ -21,15 +21,15 @@ - - + + - - - - + + + + - + diff --git a/src/Jackett.Test/WebUtilityHelpersTests.cs b/src/Jackett.Test/WebUtilityHelpersTests.cs index b1d37f49d..fbda16a74 100644 --- a/src/Jackett.Test/WebUtilityHelpersTests.cs +++ b/src/Jackett.Test/WebUtilityHelpersTests.cs @@ -30,7 +30,7 @@ namespace Jackett.Test }; //https://docs.microsoft.com/en-us/dotnet/api/system.text.codepagesencodingprovider?view=netcore-2.0 -#if NETCOREAPP2_0 +#if !NET461 if (Environment.OSVersion.Platform == PlatformID.Win32NT) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); diff --git a/src/Jackett.Tray/Jackett.Tray.csproj b/src/Jackett.Tray/Jackett.Tray.csproj index a3b0eedbd..daec5b515 100644 --- a/src/Jackett.Tray/Jackett.Tray.csproj +++ b/src/Jackett.Tray/Jackett.Tray.csproj @@ -110,7 +110,7 @@ - 2.5.0 + 2.6.0 diff --git a/src/Jackett.Updater/Jackett.Updater.csproj b/src/Jackett.Updater/Jackett.Updater.csproj index f115e19ec..0ef49e06c 100644 --- a/src/Jackett.Updater/Jackett.Updater.csproj +++ b/src/Jackett.Updater/Jackett.Updater.csproj @@ -1,7 +1,7 @@  - net461;netcoreapp2.2 + net461;netcoreapp3.0 jackett.ico JackettUpdater Exe