Skip to content

Instantly share code, notes, and snippets.

@dviererbe
Last active May 19, 2023 14:17
Show Gist options
  • Save dviererbe/b5161897b001ef0d0b7ce04974476d40 to your computer and use it in GitHub Desktop.
Save dviererbe/b5161897b001ef0d0b7ce04974476d40 to your computer and use it in GitHub Desktop.
A test script that checks if all supported RIDs are buildable via the dotnet CLI
open System
open System.IO
open System.Text.Json
let printUsage() =
printfn "Usage:"
printfn $" dotnet fsi {fsi.CommandLineArgs[0]} help"
printfn $" dotnet fsi {fsi.CommandLineArgs[0]} <path>"
printfn ""
printfn "Commands:"
printfn " help Shows this usage info."
printfn ""
printfn "Arguments:"
printfn " path File path of the json file that contains all dotnet runtime"
printfn " identifiers structured as json."
printfn ""
let printErrorMessageAndTerminate errorMessage =
Console.ForegroundColor <- ConsoleColor.Red
eprintfn errorMessage
Console.ResetColor()
printfn ""
printUsage()
Environment.Exit(-1)
let getRuntimeJsonPath() =
let containsAny array values =
array
|> Array.exists (fun x -> Array.contains x values)
if fsi.CommandLineArgs.Length < 2 then
printErrorMessageAndTerminate "Too few arguments!"
String.Empty
elif (containsAny fsi.CommandLineArgs [|"-h"; "--help"; "help"|]) then
printUsage()
Environment.Exit(0)
String.Empty
elif fsi.CommandLineArgs.Length > 2 then
printErrorMessageAndTerminate "Too many arguments!"
String.Empty
else
let path = fsi.CommandLineArgs[1]
if File.Exists(path) then
path
else
printErrorMessageAndTerminate $"File '{path}' does not exist!"
String.Empty
let parseSupportedBuildRuntimeIdentifiersFromRuntimeCompatiblityJsonFile (jsonFilePath : string) =
let supportedBaseRIDs = [| "linux-x64"; "linux-arm"; "linux-arm64"; "win-x64"; "win-x86"; "osx-arm64"; "osx-x64"; "win-arm"; "win-arm64";|]
use jsonFileStream = File.OpenRead(jsonFilePath)
use jsonDocument = JsonDocument.Parse(jsonFileStream)
jsonDocument.RootElement.EnumerateObject()
|> Seq.where (fun element ->
if element.Name = "rhel.6-x64" then
false
else
let dependsOn =
element.Value.EnumerateArray()
|> Seq.map (fun arrayElement -> arrayElement.GetString())
|> Seq.toArray
let hasSupportedBaseId =
dependsOn |> Array.exists (fun value -> (Array.contains value supportedBaseRIDs))
let dependsOnLinuxBionic =
dependsOn |> Array.contains "linux-bionic"
hasSupportedBaseId && not dependsOnLinuxBionic)
|> Seq.map (fun element -> element.Name)
// save sequence as Set because jsonDocument and jsonFileStream
// will get disposed after this function call
|> Set.ofSeq
let jsonFilePath = getRuntimeJsonPath()
parseSupportedBuildRuntimeIdentifiersFromRuntimeCompatiblityJsonFile jsonFilePath
|> Seq.iter (fun x -> (printfn "%s" x))
#!/usr/bin/env bash
# Note that this test only checks if the project builds without an error; NOT if the build artifacts run for the intended platforms.
set -eo pipefail
# TODO: replace these with the corresponding values
DOTNET_VERSION_NAME="net6.0" # or "net7.0"
RUNTIME_COMPATIBILITY_JSON_PATH="src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json"
# supress welcome banner on first run of a dotnet command
export DOTNET_NOLOGO=true
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
function Log
{
LogLevel=$1
LogMessage=$2
echo "[$LogLevel] $(date '+%H:%M:%S'): $LogMessage";
}
function LogDebug
{
LogMessage=$1
Log "DEBUG" "$LogMessage";
}
function LogInfo
{
LogMessage=$1
Log "INFO" "$LogMessage";
}
function LogWarning
{
LogMessage=$1
Log "WARNING" "$LogMessage";
}
function LogErrorAndTerminate
{
LogMessage=$1
Log "ERROR" "$LogMessage" 1>&2;
# makes shure that the shell terminates even from a subshell
kill -SIGPIPE "$$"
}
LogDebug "Reading supported .NET Runtime Identifiers"
dotnet fsi "PrintSupportedRuntimeIdentifiers.fsx" "$RUNTIME_COMPATIBILITY_JSON_PATH" | tee SupportedRuntimeIdentifiers.txt
mapfile -t SupportedDotnetRuntimeIdentifiers < SupportedRuntimeIdentifiers.txt
rm SupportedRuntimeIdentifiers.txt
cd $(mktemp -d)
LogDebug "Testing in $PWD"
declare -A LanguageProjectFileExtension
LanguageProjectFileExtension["C#"]=".csproj"
LanguageProjectFileExtension["F#"]=".fsproj"
LanguageProjectFileExtension["VB"]=".vbproj"
LANGUAGES=("C#" "F#" "VB")
for LANGUAGE in "${LANGUAGES[@]}"; do
LogDebug "Creating $LANGUAGE console template"
dotnet new console --name "HelloWorld-$LANGUAGE" --language "$LANGUAGE"
done
for RID in "${SupportedDotnetRuntimeIdentifiers[@]}"; do
for LANGUAGE in "${LANGUAGES[@]}"; do
ProjectName="HelloWorld-${LANGUAGE}"
ProjectFile="${ProjectName}/${ProjectName}${LanguageProjectFileExtension["${LANGUAGE}"]}"
ArtifactRoot="${ProjectName}/bin/Release/${DOTNET_VERSION_NAME}/${RID}"
Artifact1="${ArtifactRoot}/${ProjectName}.dll"
Artifact2="${ArtifactRoot}/publish"
LogInfo "Building $LANGUAGE Project for ${RID} with --self-contained"
dotnet publish -c Release -r "${RID}" --self-contained "$ProjectFile"
LogInfo "Check if build artifacts for ${RID} exists.";
if [[ ! -e "$Artifact1" ]]; then
LogErrorAndTerminate "Build artifact was not found: '$Artifact1'"
fi
if [[ ! -d "$Artifact2" ]]; then
LogErrorAndTerminate "Directory that would contain build artifacts was not found: '$Artifact2'"
fi
LogDebug "Cleaning build artifacts"
rm -r "$ArtifactRoot"
LogInfo "Building $LANGUAGE Project for ${RID} with --no-self-contained"
dotnet publish -c Release -r "${RID}" --no-self-contained "$ProjectFile"
LogInfo "Check if build artifacts for ${RID} exists.";
if [[ ! -e "$Artifact1" ]]; then
LogErrorAndTerminate "Build artifact was not found: '$Artifact1'"
fi
if [[ ! -d "$Artifact2" ]]; then
LogErrorAndTerminate "Directory that would contain build artifacts was not found: '$Artifact2'"
fi
LogDebug "Cleaning build artifacts"
rm -r "$ArtifactRoot"
done
done
LogInfo "Test Ok!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment