diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10e4595..9195043 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,8 +14,11 @@ jobs: fail-fast: false matrix: container_image: + - docker.io/library/alpine:edge + - docker.io/library/alpine:latest - registry.fedoraproject.org/fedora:34 - registry.fedoraproject.org/fedora:35 + - registry.fedoraproject.org/fedora:36 - registry.fedoraproject.org/fedora:rawhide - registry.access.redhat.com/ubi8 dotnet_version: @@ -25,6 +28,8 @@ jobs: exclude: - container_image: registry.fedoraproject.org/fedora:rawhide dotnet_version: "5.0" + - container_image: registry.fedoraproject.org/fedora:36 + dotnet_version: "5.0" container: image: ${{ matrix.container_image }} @@ -34,13 +39,36 @@ jobs: - name: Install build dependencies timeout-minutes: 5 run: | - dnf install -y dotnet-sdk-${{ matrix.dotnet_version }} make + set -euo pipefail + if command -v dnf; then + dnf install -y dotnet-sdk-${{ matrix.dotnet_version }} git make + elif command -v apk; then + apk add bash curl git icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ make zlib + curl -sSLO https://dot.net/v1/dotnet-install.sh + chmod +x ./dotnet-install.sh + ./dotnet-install.sh --channel ${{ matrix.dotnet_version }} + fi - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Sanity check + run: | + set -euo pipefail + PATH=$PATH:$HOME/.dotnet/ + + git config --global safe.directory "$GITHUB_WORKSPACE" + + make + mkdir -p no-reproducers + dotnet turkey/Turkey.dll no-reproducers - name: Run tests run: | set -euo pipefail + PATH=$PATH:$HOME/.dotnet/ + make check reproducers: diff --git a/Makefile b/Makefile index 9ef8fa4..4024722 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ check: run-samples: rm -rf ~/.nuget.orig && mv ~/.nuget ~/.nuget.orig && mkdir -p ~/.nuget - cd Samples && test -f ../bin/turkey && (../bin/turkey || true) + cd Samples && test -f ../turkey/Turkey.dll && (dotnet ../turkey/Turkey.dll || true) rm -rf ~/.nuget && mv ~/.nuget.orig ~/.nuget publish: diff --git a/README.md b/README.md index 8c0b2e6..849ec92 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,13 @@ It produces results in various forms, including a junit-compatible xml file. # Supported Platforms and Architectures -This is fully usable on GNU libc-based Linux distributions. This is -used by Red Hat to run .NET tests on Fedora and RHEL on multiple -architectures including 64-bit ARM, Intel x86_64 and IBM Z. +This is fully usable on GNU libc-based and musl libc-based Linux distributions. + +This is used by Red Hat to run .NET tests on Fedora and RHEL on multiple +architectures including 64-bit ARM (`aarch64`), Intel x86_64 (`x86_64`) and IBM +Z (`s390x`). + +It's also being used by other distributions, such as Alpine. # Building diff --git a/Samples/NonAlpineBashTest/test.json b/Samples/NonAlpineBashTest/test.json new file mode 100644 index 0000000..3bd0732 --- /dev/null +++ b/Samples/NonAlpineBashTest/test.json @@ -0,0 +1,13 @@ +{ + "name": "NonAlpineBashTest", + "enabled": true, + "requiresSdk": true, + "version": "1.0", + "versionSpecific": false, + "type": "bash", + "cleanup": true, + "ignoredRIDs":[ + "alpine" + ] +} + diff --git a/Samples/NonAlpineBashTest/test.sh b/Samples/NonAlpineBashTest/test.sh new file mode 100755 index 0000000..20566a4 --- /dev/null +++ b/Samples/NonAlpineBashTest/test.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "${@}" + +true diff --git a/Turkey.Tests/PlatformIdTest.cs b/Turkey.Tests/PlatformIdTest.cs index f6982b7..c5da86e 100644 --- a/Turkey.Tests/PlatformIdTest.cs +++ b/Turkey.Tests/PlatformIdTest.cs @@ -8,20 +8,32 @@ namespace Turkey.Tests public class PlatformIdTest { [Theory] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=9" }, "x64", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora9", "fedora.9", "fedora.9-x64" })] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "x64", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora30", "fedora.30", "fedora.30-x64" })] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "arm64", new string[] { "linux", "linux-arm64", "fedora", "fedora-arm64", "fedora30", "fedora.30", "fedora.30-arm64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=7" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=7.3" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.0" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.1" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=\"rhel\"", "VERSION_ID=\"8.1\"" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=centos", "VERSION_ID=8" }, "x64", new string[] { "linux", "linux-x64", "centos", "centos-x64", "centos8", "centos.8", "centos.8-x64" })] - public void BasicPlatformIds(string[] lines, string architecture, string[] expectedIds) + [InlineData(new string[] { "ID=fedora", "VERSION_ID=9" }, "x64", "", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora9", "fedora.9", "fedora.9-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "x64", "", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora30", "fedora.30", "fedora.30-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "arm64", "", new string[] { "linux", "linux-arm64", "fedora", "fedora-arm64", "fedora30", "fedora.30", "fedora.30-arm64" })] + [InlineData(new string[] { "ID=rocky", "VERSION_ID=8.5" }, "x64", "", new string[] { "linux", "linux-x64", "rocky", "rocky-x64", "rocky8", "rocky.8", "rocky.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=7" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=7.3" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.0" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.1" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=\"rhel\"", "VERSION_ID=\"8.1\"" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=centos", "VERSION_ID=8" }, "x64", "", new string[] { "linux", "linux-x64", "centos", "centos-x64", "centos8", "centos.8", "centos.8-x64" })] + [InlineData(new string[] { "ID=alpine", "VERSION_ID=3.15.2" }, "x64", "", new string[] { "linux", "linux-x64", "alpine", "alpine-x64", "alpine3.15", "alpine.3.15", "alpine.3.15-x64" })] + [InlineData(new string[] { "ID=alpine", "VERSION_ID=3.15.2" }, "x64", "musl libc", new string[] { "linux", "linux-x64", "alpine", "alpine-x64", "alpine3.15", "alpine.3.15", "alpine.3.15-x64", "linux-musl", "linux-musl-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=39" }, "x64", "GNU libc", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora39", "fedora.39", "fedora.39-x64" })] + public void BasicPlatformIds(string[] osReleaseLines, string architecture, string lddOutput, string[] expectedIds) { - var result = new PlatformId().GetPlatformIdsFromOsRelease(lines, architecture); + var result = new PlatformId().ComputePlatformIds(osReleaseLines, architecture, lddOutput); Assert.Equal(expectedIds.ToList(), result); } + + [Fact] + public void LddWorks() + { + string version = new PlatformId().GetLddVersion(); + Assert.NotNull(version); + Assert.NotEmpty(version); + } } } diff --git a/Turkey/AssemblyInfo.cs b/Turkey/AssemblyInfo.cs new file mode 100644 index 0000000..2dde274 --- /dev/null +++ b/Turkey/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("Turkey.Tests")] diff --git a/Turkey/PlatformId.cs b/Turkey/PlatformId.cs index 6d343dc..cae1728 100644 --- a/Turkey/PlatformId.cs +++ b/Turkey/PlatformId.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Diagnostics; namespace Turkey { @@ -11,37 +13,53 @@ public class PlatformId public List CurrentIds { // TODO make this async? - get => GetPlatformIdsFromOsRelease(File.ReadAllLines("/etc/os-release")); + get => ComputePlatformIds(File.ReadAllLines("/etc/os-release"), GetLddVersion()); } - public List GetPlatformIdsFromOsRelease(string[] lines) + public List ComputePlatformIds(string[] osReleaseLines, string lddVersionOutput) { string arch = Enum.GetName(typeof(Architecture), RuntimeInformation.OSArchitecture).ToLowerInvariant(); - return GetPlatformIdsFromOsRelease(lines, arch); + return ComputePlatformIds(osReleaseLines, arch, lddVersionOutput); } - public List GetPlatformIdsFromOsRelease(string[] lines, string architecture) + public List ComputePlatformIds(string[] osReleaseLines, string architecture, string lddVersionOutput) { - var id = GetValue("ID", lines); + var id = GetValue("ID", osReleaseLines); id = Unquote(id); - var versionId = GetValue("VERSION_ID", lines); + var versionId = GetValue("VERSION_ID", osReleaseLines); versionId = Unquote(versionId); - if (id.Equals("rhel", StringComparison.Ordinal)) + var needsLastVersionRemoved = new string[] { "almalinux", "alpine", "ol", "rhel", "rocky" } + .Any(os => id.Equals(os, StringComparison.Ordinal)); + if (needsLastVersionRemoved) { - int indexOfDot = versionId.IndexOf(".", StringComparison.Ordinal); + int indexOfDot = versionId.LastIndexOf(".", StringComparison.Ordinal); if (indexOfDot > 0) { versionId = versionId.Substring(0, indexOfDot); } } - var platforms = new string[] { + var platforms = new List() + { "linux", "linux" + "-" + architecture, id, id + "-" + architecture, id + versionId, id + "." + versionId, - id + "." + versionId + "-" + architecture }; + id + "." + versionId + "-" + architecture + }; + + bool isMusl = lddVersionOutput.Contains("musl", StringComparison.Ordinal); + + if (isMusl) + { + platforms.AddRange(new [] + { + "linux-musl", + "linux-musl" + "-" + architecture, + }); + + } return platforms.ToList(); } @@ -62,5 +80,20 @@ private string Unquote(string text) return text; } + + internal string GetLddVersion() + { + using (Process p = new Process()) + { + p.StartInfo.FileName = "ldd"; + p.StartInfo.Arguments = "--version"; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; + p.Start(); + p.WaitForExit(); + + return string.Concat(p.StandardOutput.ReadToEnd(), p.StandardError.ReadToEnd()); + } + } } }