From d5ff5db55e804a2c84c7642a2857f561b8d56a28 Mon Sep 17 00:00:00 2001 From: Joshua Potter Date: Sun, 26 Nov 2023 16:38:55 -0700 Subject: [PATCH] Add mix spec. (#8) Allows pinning the version of mix used to generate new Elixir projects. --- specs/mix/runner | 13 ++++++ specs/mix/spec.json | 6 +++ specs/mix/template/.envrc | 3 ++ specs/mix/template/README.md | 25 +++++++++++ specs/mix/template/default.nix | 10 +++++ specs/mix/template/deps.nix | 13 ++++++ specs/mix/template/flake.lock | 76 ++++++++++++++++++++++++++++++++++ specs/mix/template/flake.nix | 66 +++++++++++++++++++++++++++++ 8 files changed, 212 insertions(+) create mode 100755 specs/mix/runner create mode 100644 specs/mix/spec.json create mode 100644 specs/mix/template/.envrc create mode 100644 specs/mix/template/README.md create mode 100644 specs/mix/template/default.nix create mode 100644 specs/mix/template/deps.nix create mode 100644 specs/mix/template/flake.lock create mode 100644 specs/mix/template/flake.nix diff --git a/specs/mix/runner b/specs/mix/runner new file mode 100755 index 0000000..670372e --- /dev/null +++ b/specs/mix/runner @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +cp -r template/. "$OUT" + +# Generate a new project with the specified name using `mix`. Pipe in `yes` +# since `mix` requires confirmation when writing out to a directory that already +# has content. +nix develop "$OUT" --command bash -c "yes | mix new $OUT --app '$APP'" + +# Replace the template name of the flake.nix file with the new app name. The +# mix generator would fail if `$APP` does not consist of just lowercase ASCII +# letters, numbers, or underscores. Thus the following command is safe. +sed -i "s//$APP/g" "$OUT/flake.nix" diff --git a/specs/mix/spec.json b/specs/mix/spec.json new file mode 100644 index 0000000..fa31cb2 --- /dev/null +++ b/specs/mix/spec.json @@ -0,0 +1,6 @@ +{ + "app": { + "type": "text", + "prompt": "App Name> " + } +} diff --git a/specs/mix/template/.envrc b/specs/mix/template/.envrc new file mode 100644 index 0000000..b9238c3 --- /dev/null +++ b/specs/mix/template/.envrc @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +use flake diff --git a/specs/mix/template/README.md b/specs/mix/template/README.md new file mode 100644 index 0000000..887a7ed --- /dev/null +++ b/specs/mix/template/README.md @@ -0,0 +1,25 @@ +# Mix Flake Template + +This is a template for constructing a working environment for Elixir development +(version 1.15.7, Erlang/OTP 25) with the [mix](https://hexdocs.pm/mix/1.12/Mix.html) +tool. [direnv](https://direnv.net/) can be used to launch a dev shell upon +entering this directory (refer to `.envrc`). Otherwise run via: +```bash +$> nix develop +``` + +## Language Server + +The [elixir-ls](https://github.com/elixir-lsp/elixir-ls) LSP (version 0.17.10) +is included in this flake. + +## Dependencies + +This project pins Mix dependencies using [mix2nix](https://github.com/ydlr/mix2nix). +After updating your `mix.lock` file, make sure to re-run the following: +```bash +mix2nix > deps.nix +``` +As of now, `mix2nix` cannot handle git dependencies found inside the `mix.lock` +file. If you have git dependencies, add them manually or use +[FODs](https://nixos.org/manual/nixpkgs/stable/#packaging-beam-applications). diff --git a/specs/mix/template/default.nix b/specs/mix/template/default.nix new file mode 100644 index 0000000..f620865 --- /dev/null +++ b/specs/mix/template/default.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).defaultNix diff --git a/specs/mix/template/deps.nix b/specs/mix/template/deps.nix new file mode 100644 index 0000000..06dc971 --- /dev/null +++ b/specs/mix/template/deps.nix @@ -0,0 +1,13 @@ +{ lib, beamPackages, overrides ? (x: y: {}) }: + +let + buildRebar3 = lib.makeOverridable beamPackages.buildRebar3; + buildMix = lib.makeOverridable beamPackages.buildMix; + buildErlangMk = lib.makeOverridable beamPackages.buildErlangMk; + + self = packages // (overrides self packages); + + packages = with beamPackages; with self; { + + }; +in self diff --git a/specs/mix/template/flake.lock b/specs/mix/template/flake.lock new file mode 100644 index 0000000..035b7da --- /dev/null +++ b/specs/mix/template/flake.lock @@ -0,0 +1,76 @@ +{ + "nodes": { + "flake-compat": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1700794826, + "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/specs/mix/template/flake.nix b/specs/mix/template/flake.nix new file mode 100644 index 0000000..f17ea07 --- /dev/null +++ b/specs/mix/template/flake.nix @@ -0,0 +1,66 @@ +{ + description = '' + An opinionated mix flake. + + To generate a copy of this template elsewhere, run: + > bootstrap mix + ''; + + inputs = { + flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + inherit (pkgs.beam.packages.erlang_25) + beamPackages + buildMix + elixir + elixir-ls + hex + mixRelease; + + deps = import ./deps.nix { + lib = pkgs.lib; + inherit beamPackages; + }; + in + { + packages = { + lib = buildMix { + name = ""; + src = ./.; + version = "0.1.0"; + beamDeps = builtins.attrValues deps; + }; + + app = mixRelease { + pname = ""; + src = ./.; + version = "0.1.0"; + mixNixDeps = deps; + }; + + default = self.packages.${system}.lib; + }; + + devShells.default = pkgs.mkShell { + inputsFrom = [ + self.packages.${system}.app + self.packages.${system}.lib + ]; + packages = [ + elixir + elixir-ls + hex + ] ++ (with pkgs; [ + mix2nix + ]); + }; + }); +}