diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8b2429491..1bf53f1e3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -80,6 +80,10 @@ stages: artifact: LinuxCoreTests displayName: Publish Linux Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) + - publish: '$(testsFolder)/netcoreapp3.1/linux-musl-x64/publish' + artifact: LinuxMuslCoreTests + displayName: Publish Linux Musl Test Package + condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/netcoreapp3.1/osx-x64/publish' artifact: MacCoreTests displayName: Publish MacOS Test Package @@ -225,7 +229,15 @@ stages: includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-x64/netcoreapp3.1 - task: ArchiveFiles@2 - displayName: Create ARM32 Core tar + displayName: Create Linux Musl Core tar + inputs: + archiveFile: '$(Build.ArtifactStagingDirectory)/Readarr.$(buildName).linux-musl-core-x64.tar.gz' + archiveType: 'tar' + tarCompression: 'gz' + includeRootFolder: false + rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/netcoreapp3.1 + - task: ArchiveFiles@2 + displayName: Create ARM32 Linux Core tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Readarr.$(buildName).linux-core-arm.tar.gz' archiveType: 'tar' @@ -240,6 +252,14 @@ stages: tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-arm64/netcoreapp3.1 + - task: ArchiveFiles@2 + displayName: Create ARM64 Linux Musl Core tar + inputs: + archiveFile: '$(Build.ArtifactStagingDirectory)/Readarr.$(buildName).linux-musl-core-arm64.tar.gz' + archiveType: 'tar' + tarCompression: 'gz' + includeRootFolder: false + rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/netcoreapp3.1 - publish: $(Build.ArtifactStagingDirectory) artifact: 'Packages' displayName: Publish Packages @@ -346,13 +366,20 @@ stages: matrix: mono520: testName: 'Mono 5.20' - containerImage: lidarr/testimages:mono-5.20 - mono608: - testName: 'Mono 6.8' - containerImage: lidarr/testimages:mono-6.8 + artifactName: LinuxTests + containerImage: servarr/testimages:mono-5.20 mono610: testName: 'Mono 6.10' - containerImage: lidarr/testimages:mono-6.10 + artifactName: LinuxTests + containerImage: servarr/testimages:mono-6.10 + mono612: + testName: 'Mono 6.12' + artifactName: LinuxTests + containerImage: servarr/testimages:mono-6.12 + alpine: + testName: 'Musl Net Core' + artifactName: LinuxMuslCoreTests + containerImage: servarr/testimages:alpine pool: vmImage: 'ubuntu-18.04' @@ -362,8 +389,6 @@ stages: timeoutInMinutes: 10 steps: - - bash: mono --version - displayName: Check Mono version - task: UseDotNet@2 displayName: 'Install .net core' inputs: @@ -373,10 +398,14 @@ stages: displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: LinuxTests + artifactName: $(artifactName) targetPath: $(testsFolder) + - bash: find ${TESTSFOLDER} -name "Readarr.Test.Dummy" -exec chmod a+x {} \; + displayName: Make Test Dummy Executable + condition: and(succeeded(), ne(variables['osName'], 'Windows')) - bash: | chmod a+x ${TESTSFOLDER}/test.sh + ls -lR ${TESTSFOLDER} ${TESTSFOLDER}/test.sh Linux Unit Test displayName: Run Tests - task: PublishTestResults@2 @@ -469,16 +498,24 @@ stages: matrix: mono520: testName: 'Mono 5.20' - containerImage: lidarr/testimages:mono-5.20 - mono608: - testName: 'Mono 6.8' - containerImage: lidarr/testimages:mono-6.8 + artifactName: LinuxTests + containerImage: servarr/testimages:mono-5.20 + pattern: 'Readarr.**.linux.tar.gz' mono610: testName: 'Mono 6.10' - containerImage: lidarr/testimages:mono-6.10 - - variables: - pattern: 'Readarr.**.linux.tar.gz' + artifactName: LinuxTests + containerImage: servarr/testimages:mono-6.10 + pattern: 'Readarr.**.linux.tar.gz' + mono612: + testName: 'Mono 6.12' + artifactName: LinuxTests + containerImage: servarr/testimages:mono-6.12 + pattern: 'Readarr.**.linux.tar.gz' + alpine: + testName: 'Musl Net Core' + artifactName: LinuxCoreTests + containerImage: servarr/testimages:alpine + pattern: 'Readarr.**.linux-musl-core-x64.tar.gz' pool: vmImage: 'ubuntu-18.04' @@ -488,8 +525,6 @@ stages: timeoutInMinutes: 15 steps: - - bash: mono --version - displayName: Check Mono version - task: UseDotNet@2 displayName: 'Install .net core' inputs: @@ -499,7 +534,7 @@ stages: displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: LinuxTests + artifactName: $(artifactName) targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact diff --git a/build.sh b/build.sh index c2ff46a91..5e3395a59 100755 --- a/build.sh +++ b/build.sh @@ -321,6 +321,7 @@ then then PackageTests "netcoreapp3.1" "win-x64" PackageTests "netcoreapp3.1" "linux-x64" + PackageTests "netcoreapp3.1" "linux-musl-x64" PackageTests "netcoreapp3.1" "osx-x64" PackageTests "net462" "linux-x64" else @@ -352,7 +353,9 @@ then then Package "netcoreapp3.1" "win-x64" Package "netcoreapp3.1" "linux-x64" + Package "netcoreapp3.1" "linux-musl-x64" Package "netcoreapp3.1" "linux-arm64" + Package "netcoreapp3.1" "linux-musl-arm64" Package "netcoreapp3.1" "linux-arm" Package "netcoreapp3.1" "osx-x64" Package "net462" "linux-x64" diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 01a5ac2e9..7f0c3887f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,8 +6,8 @@ AnyCPU true - win-x64;osx-x64;linux-x64;linux-arm;linux-arm64 - win-x64:net462;osx-x64:net462;linux-arm:net462;linux-arm64:net462 + win-x64;osx-x64;linux-x64;linux-musl-x64;linux-arm;linux-arm64;linux-musl-arm64 + win-x64:net462;osx-x64:net462;linux-arm:net462;linux-arm64:net462;linux-musl-x64:net462;linux-musl-arm64:net462 $(MSBuildThisFileDirectory)..\ diff --git a/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs index 1a2b6ce9d..09035be21 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using NLog; @@ -11,7 +12,7 @@ namespace NzbDrone.Common.EnvironmentInfo public static Os Os { get; } public static bool IsNotWindows => !IsWindows; - public static bool IsLinux => Os == Os.Linux; + public static bool IsLinux => Os == Os.Linux || Os == Os.LinuxMusl || Os == Os.Bsd; public static bool IsOsx => Os == Os.Osx; public static bool IsWindows => Os == Os.Windows; @@ -37,18 +38,7 @@ namespace NzbDrone.Common.EnvironmentInfo case PlatformID.MacOSX: case PlatformID.Unix: { - // Sometimes Mac OS reports itself as Unix - if (Directory.Exists("/System/Library/CoreServices/") && - (File.Exists("/System/Library/CoreServices/SystemVersion.plist") || - File.Exists("/System/Library/CoreServices/ServerVersion.plist"))) - { - Os = Os.Osx; - } - else - { - Os = Os.Linux; - } - + Os = GetPosixFlavour(); break; } } @@ -92,6 +82,48 @@ namespace NzbDrone.Common.EnvironmentInfo IsDocker = true; } } + + private static Os GetPosixFlavour() + { + var output = RunAndCapture("uname", "-s"); + + if (output.StartsWith("Darwin")) + { + return Os.Osx; + } + else if (output.Contains("BSD")) + { + return Os.Bsd; + } + else + { + return IsMusl() ? Os.LinuxMusl : Os.Linux; + } + } + + private static bool IsMusl() + { + var output = RunAndCapture("ldd", "/bin/ls"); + return output.Contains("libc.musl"); + } + + private static string RunAndCapture(string filename, string args) + { + Process p = new Process(); + p.StartInfo.FileName = filename; + p.StartInfo.Arguments = args; + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; + + p.Start(); + + // To avoid deadlocks, always read the output stream first and then wait. + string output = p.StandardOutput.ReadToEnd(); + p.WaitForExit(1000); + + return output; + } } public interface IOsInfo @@ -107,6 +139,8 @@ namespace NzbDrone.Common.EnvironmentInfo { Windows, Linux, - Osx + Osx, + LinuxMusl, + Bsd } } diff --git a/src/NzbDrone.Mono.Test/Readarr.Mono.Test.csproj b/src/NzbDrone.Mono.Test/Readarr.Mono.Test.csproj index d96c5adc2..b97c74aeb 100644 --- a/src/NzbDrone.Mono.Test/Readarr.Mono.Test.csproj +++ b/src/NzbDrone.Mono.Test/Readarr.Mono.Test.csproj @@ -21,7 +21,7 @@ See https://github.com/xamarin/XamarinComponents/issues/282 --> - + diff --git a/src/NzbDrone.Mono/Readarr.Mono.csproj b/src/NzbDrone.Mono/Readarr.Mono.csproj index ada027960..e683460e7 100644 --- a/src/NzbDrone.Mono/Readarr.Mono.csproj +++ b/src/NzbDrone.Mono/Readarr.Mono.csproj @@ -14,7 +14,7 @@ See https://github.com/xamarin/XamarinComponents/issues/282 --> - + diff --git a/src/Runtimes/linux-musl-x64/libMonoPosixHelper.so b/src/Runtimes/linux-musl-x64/libMonoPosixHelper.so new file mode 100644 index 000000000..edcf49366 Binary files /dev/null and b/src/Runtimes/linux-musl-x64/libMonoPosixHelper.so differ