Skip to content

Instantly share code, notes, and snippets.

@mtrsk
Forked from steinuil/Nuget2Nix.fsx
Created April 24, 2020 14:23
Show Gist options
  • Save mtrsk/6eeee3b1a564ecb6864fc56e8434a796 to your computer and use it in GitHub Desktop.
Save mtrsk/6eeee3b1a564ecb6864fc56e8434a796 to your computer and use it in GitHub Desktop.
Code for the .NET packaging post
{
nixpkgs.overlays = [ (import ./my-overlay.nix) ];
environment.systemPackages = with pkgs; [ kino-bot ];
systemd.services.kino-bot = {
enable = true;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "on-failure";
ExecStart = "${pkgs.kino-bot}/bin/KinoBot --token ${secrets.kinoBotToken}";
};
};
}
{ stdenv, fetchurl, libunwind, openssl, icu, libuuid, zlib, curl }:
let
rpath = stdenv.lib.makeLibraryPath [ stdenv.cc.cc libunwind libuuid icu openssl zlib curl ];
dynamicLinker = stdenv.cc.bintools.dynamicLinker;
platform = "linux-arm64";
sha512 = "34k6cm69gxm7vcd9m6bp47sdx96j32z6lfhb2vjcdznc6xgs2wy8zcang3b1mjm5919dq7v6iysm6ffcpgjhhphy7prlnaqa69q5mks";
in stdenv.mkDerivation rec {
pname = "dotnet-sdk";
version = "3.1.102";
src = fetchurl {
inherit sha512;
url = "https://dotnetcli.azureedge.net/dotnet/Sdk/${version}/${pname}-${version}-${platform}.tar.gz";
};
sourceRoot = ".";
dontPatchELF = true;
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp -r ./ $out
ln -s $out/dotnet $out/bin/dotnet
runHook postInstall
'';
postFixup = ''
patchelf --set-interpreter "${dynamicLinker}" --set-rpath "${rpath}" $out/dotnet
find $out -type f -name "*.so" -exec patchelf --set-rpath '$ORIGIN:${rpath}' {} ';'
find $out -type f -name "apphost" -exec patchelf --set-interpreter "${dynamicLinker}" --set-rpath '$ORIGIN:${rpath}' {} ';'
'';
doInstallCheck = true;
installCheckPhase = ''
$out/bin/dotnet --info
'';
meta = with stdenv.lib; {
homepage = https://dotnet.microsoft.com/;
description = "The .NET software framework SDK";
platforms = [ "aarch64-linux" ];
maintainers = with maintainers; [ kuznero ];
license = licenses.mit;
};
}
{ stdenv, libunwind, openssl_1_0_2, icu, libuuid, zlib, curl, callPackage, dotnet-sdk }:
let
rpath = stdenv.lib.makeLibraryPath [ stdenv.cc.cc libunwind libuuid icu openssl_1_0_2 zlib curl ];
nugetPkgs = callPackage (import ./kino-bot-nuget.nix) {} "kino-bot";
in stdenv.mkDerivation rec {
pname = "kino-bot";
version = "2020-03-29";
src = builtins.fetchGit {
name = "${pname}-${version}-git";
url = https://github.com/steinuil/KinoBot;
ref = "master";
rev = "275ae0447ab1ab21cba76bb673f00559ed5d9251";
};
buildInputs = [ dotnet-sdk nugetPkgs.cache ];
buildPhase = ''
export DOTNET_NOLOGO=1
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export HOME="$(mktemp -d)"
dotnet publish --nologo \
-r linux-arm64 --self-contained \
--source "${nugetPkgs.cache}" -c Release -o out
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp -r ./out/* $out
ln -s $out/KinoBot $out/bin/KinoBot
runHook postInstall
'';
dontPatchELF = true;
postFixup = ''
patchelf \
--set-interpreter "${stdenv.cc.bintools.dynamicLinker}" \
--set-rpath '$ORIGIN:${rpath}' $out/KinoBot
find $out -type f -name "*.so" -exec \
patchelf --set-rpath '$ORIGIN:${rpath}' {} ';'
'';
meta = with stdenv.lib; {
description = "The Movie Night server bot";
homepage = https://github.com/steinuil/KinoBot;
platforms = [ "aarch64-linux" ];
license = licenses.isc;
};
}
self: super: {
dotnet-sdk = super.callPackage ./pkgs/dotnet-sdk.nix {};
kino-bot = super.callPackage ./pkgs/kino-bot.nix {};
}
open System
open System.IO
open System.Net
open System.Text.Json
open System.Collections.Generic
open System.Security.Cryptography
/// Taken from hash.cc in the nix codebase
/// https://github.com/NixOS/nix/blob/a7540294cfae82c098e8691cd5212a9184add574/src/libutil/hash.cc
module Base32 =
let chars = "0123456789abcdfghijklmnpqrsvwxyz"
let length size =
(size * 8 - 1) / 5 + 1
let fromBytes (bytes : byte[]) =
seq {
for n = length bytes.Length - 1 downto 0 do
let b = n * 5
let i = b / 8
let j = b % 8
yield int bytes.[i] >>> j ||| if i >= bytes.Length - 1 then 0 else int bytes.[i + 1] <<< (8 - j)
}
|> Seq.map (fun c -> chars.[c &&& 0x1f])
|> Seq.toArray
|> String
let fromBase64 = Convert.FromBase64String >> fromBytes
let readFile<'T> f = File.ReadAllText(f) |> JsonSerializer.Deserialize<'T>
let serialize<'T> o = JsonSerializer.Serialize<'T>(o)
let httpGet url =
let uri = Uri(url)
let req = HttpWebRequest.CreateHttp(uri, Method = "GET", AllowAutoRedirect = true)
let resp = req.GetResponse()
resp.GetResponseStream()
let sha512FromStream (stream : Stream) =
use hash = SHA512.Create()
hash.ComputeHash stream
[<CLIMutable>]
type Dependency = {
resolved : string
}
[<CLIMutable>]
type PackagesLock = {
dependencies : Dictionary<string, Dictionary<string, Dependency>>
}
type FetchUrlArgs = {
nixName : string
baseName : string
version : string
sha512 : string
}
let toFetchUrlArgs (pl : PackagesLock) =
pl.dependencies.Values
|> Seq.concat
|> Seq.map (fun kv -> kv.Key, kv.Value.resolved)
|> Seq.append [
"Microsoft.AspNetCore.App.Runtime.linux-arm64", "3.1.2"
"Microsoft.NETCore.App.Host.linux-arm64", "3.1.2"
"Microsoft.NETCore.App.Runtime.linux-arm64", "3.1.2"
]
|> Seq.distinct
|> Seq.map (fun (name, version) ->
printfn "fetching %s v%s" name version
let sha512 =
sprintf "https://www.nuget.org/api/v2/package/%s/%s" name version
|> httpGet
|> sha512FromStream
|> Base32.fromBytes
{
nixName = name
baseName = name
version = version
sha512 = sha512
}
)
let argv = Environment.GetCommandLineArgs()
let out = new StreamWriter("nuget.nix")
fprintf out "{ fetchurl, unzip, linkFarm, lib, stdenvNoCC }:"
fprintf out """
let fetchNuGet = { baseName, version, sha512 }:
let nupkgName = lib.strings.toLower "${baseName}.${version}.nupkg"; in
stdenvNoCC.mkDerivation {
name = "${baseName}-${version}";
src = fetchurl {
inherit sha512;
url = "https://www.nuget.org/api/v2/package/${baseName}/${version}";
name = "${baseName}.${version}.zip";
};
sourceRoot = ".";
buildInputs = [ unzip ];
dontStrip = true;
installPhase = ''
mkdir -p $out
chmod +r *.nuspec
cp *.nuspec $out
cp $src $out/${nupkgName}
'';
};
in
"""
fprintf out "name: rec {\n"
fprintf out " cache = linkFarm \"${name}-nuget-pkgs\" packages;\n"
fprintf out " packages = [\n"
argv.[argv.Length - 1]
|> readFile<PackagesLock>
|> toFetchUrlArgs
|> Seq.iter (fun args ->
fprintf out " { name = \"%s\";\n" args.nixName
fprintf out " path = fetchNuGet {\n"
fprintf out " baseName = \"%s\";\n" args.baseName
fprintf out " version = \"%s\";\n" args.version
fprintf out " sha512 = \"%s\";\n" args.sha512
fprintf out " };\n"
fprintf out " }\n"
)
fprintf out " ];\n"
fprintf out "}\n"
out.Flush()
out.Close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment