Skip to content

Commit

Permalink
Another article (#18)
Browse files Browse the repository at this point in the history
* add another article

* add another article

* add another article
  • Loading branch information
mtrsk authored Sep 16, 2024
1 parent fa59a62 commit cdbcf8b
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*.html linguist-vendored
*.scss linguist-vendored
*.png filter=lfs diff=lfs merge=lfs -text
static/img/you_have_10_seconds_to_nixify_your_dotnet_project/01_demo.gif filter=lfs diff=lfs merge=lfs -text
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true

- name: Install Nix
uses: cachix/install-nix-action@v27
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
lfs: true

- name: Install Nix
uses: cachix/install-nix-action@v27
Expand Down
194 changes: 194 additions & 0 deletions blog/posts/you-have-10-seconds-to-nixify-your-dotnet-project.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#+CAPTION: Don "The Gun" Syme, now officially part of the "Nix Gang".
#+NAME: fig:gun-syme
[[../../static/img/you_have_10_seconds_to_nixify_your_dotnet_project/00_don_gun.png]]

While this is a click bait title (maybe I've also farmed some zoomer credits out
the OC), I'm pretty sure that's how Don Syme feels when looks at a [[https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/results][Result]] type
like ~Result<'T,string>~ in an F# codebase. The reason why I've written this post
is that I started doing changes in a [[https://github.com/mtrsk/interval.fs][open source project]] I develop/maintain,
and realized other .Net people could benefit from this somehow (as most of the
Nix + .Net guides are from before 2024).

* An Opinionated Template

Turns out that, while writing this, I've decided to put everything in a template
that's easy to +steal+ copy, so if you are from the future and have the [[https://nixos.org/download/][Nix (the
package manager)]] and the [[https://nixos.wiki/wiki/Flakes][Flakes]] feature enabled you'll be able to reproduce this
post. Additionally, someone beat me into writing a flake for F#, here's [[https://github.com/NixOS/templates/tree/master/dotnet][a more
official take]] on it, there are a couple changes from my repo and this one,
mostly because I tend to favor devenv (since it has shown better adoption when I
preached it to non-Nixers).

** Devenv

I've already tackled this in a [[https://mtrsk.github.io/blog/2024/some-experiments-with-erlang-and-nix/][previous article]], but the best developer
experience right now is with [[https://devenv.sh/][devenv.sh]]. Unlike the previous article tho, the
environment setup is way simpler, just a bunch of .Net tools inside the shell
and call it a day.

#+BEGIN_SRC nix
#(...)
# `nix develop --impure`
default = devenv.lib.mkShell {
inherit inputs pkgs;
modules = [
(
{ pkgs, lib, ... }:
{
packages = with pkgs; [
bash
just

# for dotnet
netcoredbg
fsautocomplete
fantomas
];

languages.dotnet = {
enable = true;
package = dotnet;
};

# looks for the .env by default additionaly, there is .filename
# if an arbitrary file is desired
dotenv.enable = true;
}
)
];
};
# (...)
#+END_SRC

and similary to the previous post, we can access the environment by doing:

#+BEGIN_SRC shell
nix develop --impure
#+END_SRC

or, if you have [[https://github.com/direnv/direnv][direnv]], run ~direnv allow~. Now you can build the project with the
usual .Net tooling:

#+BEGIN_SRC shell
dotnet build
# There is also a justfile configured to you can just
# type "just" and get all commands
#+END_SRC

Here's a quick demo:

#+NAME: fig:demo
[[../../static/img/you_have_10_seconds_to_nixify_your_dotnet_project/01_demo.gif]]

** Build your project with Nix

This project is just a simple solution with the basic [[https://learn.microsoft.com/en-us/dotnet/fsharp/get-started/get-started-command-line][CLI Console App]] from the
official documentation, the difference being that I've added a dependency to
[[https://github.com/demystifyfp/FsToolkit.ErrorHandling][FsToolkit.ErrorHandling]], just as a way to showcase how to handle nuget
dependencies later. To package your .Net App there is already the [[https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/dotnet.section.md#packaging-a-dotnet-application-packaging-a-dotnet-application][buildDotNetModule]],
you can explore all the other options later in the docs, this is what works for
the current code:

#+BEGIN_SRC nix
# `nix build`
default = pkgs.buildDotnetModule {
pname = name;
version = version;
src = ./.;
projectFile = "src/App/App.fsproj";
nugetDeps = ./deps.nix;

dotnet-sdk =
with pkgs.dotnetCorePackages;
combinePackages [
sdk_8_0
];
dotnet-runtime = pkgs.dotnetCorePackages.sdk_8_0;
};
#+END_SRC

To properly build this with nix, you may have noticed that we also import a
~deps.nix~ file in the previous step. This file contains all the nuget
dependencies our project uses and their hashes:

#+BEGIN_SRC nix
{ fetchNuGet }: [
(fetchNuGet { pname = "FsToolkit.ErrorHandling"; version = "4.16.0"; hash = "sha256-4pRixOtRDgLt4/z71o1XnkuXRa/43LUhl/pDRpofX7s="; })
]
#+END_SRC

You don't have to manually create or edit this, as its already documented
[[https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/dotnet.section.md#generating-and-updating-nuget-dependencies-generating-and-updating-nuget-dependencies][here]]. In this project this is already handled by the ~just gen-deps~ (or ~just gd~)
command:

#+BEGIN_SRC shell
$ rm deps.nix
$ just gd
dotnet restore --packages out
Determining projects to restore...
All projects are up-to-date for restore.
nix run nixpkgs#nuget-to-nix -- out > deps.nix
$ cat deps.nix
{ fetchNuGet }: [
(fetchNuGet { pname = "FsToolkit.ErrorHandling"; version = "4.16.0"; hash = "sha256-4pRixOtRDgLt4/z71o1XnkuXRa/43LUhl/pDRpofX7s="; })
]
#+END_SRC

The previous step is also the usual way to update a .Net package in nixpkgs, most
times you'll just need to get the new version hash and update the nuget hashes
as well:

#+BEGIN_SRC shell
$ cd <my-clone-of-nixpkgs>
$ nix-build -A <package-name>.passthru.fetch-deps | bash
$ nix-build -A <package-name>
#+END_SRC

Then you open a PR to the [[https://github.com/NixOS/nixpkgs][official repository]], following the [[https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md][contribution
guidelines]], of course. Now, going back to the testing the Nix build:

#+BEGIN_SRC shell
$ nix build
$ ./result/bin/App
Test
# It works
#+END_SRC

** Generating OCI Images

Similar to the [[https://mtrsk.github.io/blog/2024/some-experiments-with-erlang-and-nix/][previous post]], the Container Image looks like this:

#+BEGIN_SRC shell
# nix build .#dockerImage
dockerImage = pkgs.dockerTools.buildLayeredImage {
name = "sample";
tag = "latest";
created = "now";
contents = [ default ];
config = {
Cmd = [
"${default}/bin/App"
];
};
};
#+END_SRC

And can be tested with:

#+BEGIN_SRC shell
$ nix build .#dockerImage
$ docker load < ./result
$ docker container run --rm sample:latest
Test
#+END_SRC

* Conclusion

If this sparkled your interest somehow, here's the [[https://github.com/mtrsk/fsharp-nix/tree/master][source code]], I've also made
sure to configure some [[https://github.com/mtrsk/fsharp-nix/actions][Github Actions]] Workflows there.

** TODO
- [ ] Optimize the container image, by just shipping the runtime, not the SDK.
- [ ] Open a PR into the [[https://github.com/NixOS/templates/tree/master/dotnet][NixOS Templates]] repo, maybe adding a [[https://safe-stack.github.io/][SAFE]] stack example
as well and a container build into the Hello Example.

10 changes: 10 additions & 0 deletions content-org/content.org
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ This page is a rendered version of my [[https://en.wikipedia.org/wiki/OPML][OPML

#+INCLUDE: "../blog/blog.org"

** You have 10 seconds to nixify your .Net project
:PROPERTIES:
:EXPORT_FILE_NAME: you-have-10-seconds-to-nixify-your-dotnet-project
:EXPORT_DATE: 2024-09-16
:EXPORT_HUGO_CUSTOM_FRONT_MATTER: :slug you-have-10-seconds-to-nixify-your-dotnet-project
:CUSTOM_ID: you-have-10-seconds-to-nixify-your-dotnet-project
:END:

#+INCLUDE: "../blog/posts/you-have-10-seconds-to-nixify-your-dotnet-project.org"

** Some experiments with Erlang and Nix
:PROPERTIES:
:EXPORT_FILE_NAME: some-experiments-with-erlang-and-nix
Expand Down
2 changes: 1 addition & 1 deletion export.el
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

;; Configuration Variables:
(setq content-dir (concat (getenv "PWD") "/content-org"))
(setq org-hugo-base-di (concat (getenv "PWD") "/content-org"))
(setq org-hugo-base-dir (concat (getenv "PWD") "/content-org"))

;; Don't ask for confirmation before evaluating a code block
(setq org-confirm-babel-evaluate nil)
Expand Down
Binary file modified static/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/img/some_experiments_with_nix_and_erlang/01_postgres.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit cdbcf8b

Please sign in to comment.