From 3384dd8206d02871a5dc48f3ea18be27c6103058 Mon Sep 17 00:00:00 2001 From: Brian May Date: Sun, 19 Nov 2023 09:18:54 +1100 Subject: [PATCH] Add nix flake This will add support for nix flakes. Which really helps with my development on nixos. This has two basic parts: 1. DEVELOPMENT After this you can use the following commands on computer with nix and a patched version of direnv: direnv allow devenv up And it will automatically start and instance of postgresql and mosquitto for development. And the environment variables are already configured for teslamate. So then can start teslamate with: npm install --prefix ./assets && npm run deploy --prefix ./assets iex -S mix phx.server This part is all working as designed. And pretty simple and straight forward. 2. NIX PACKAGE OF TESLA This is 99% complete, but some pain points I haven't addressed yet. Because I don't yet know of good solutions. * There are two checksums in flake.nix that needs to be updated whenever mix.lock or package-lock.json changes. --- .envrc | 1 + .gitignore | 9 ++ CHANGELOG.md | 1 + assets/package-lock.json | 14 ++- config/runtime.exs | 2 + flake.lock | 253 ++++++++++++++++++++++++++++++++++++++ flake.nix | 153 +++++++++++++++++++++++ lib/teslamate_web/cldr.ex | 4 +- 8 files changed, 433 insertions(+), 4 deletions(-) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..cffc922b00 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake . --impure diff --git a/.gitignore b/.gitignore index 5583cbfd6b..bdae8e91ef 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,12 @@ config/*.env /priv/plts/*.plt /priv/plts/*.plt.hash + +# Nix files +/.direnv +/.devenv +/tzdata/ +/result + +# Used during tests +/tmp/ diff --git a/CHANGELOG.md b/CHANGELOG.md index da2e398af5..5025ee35ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ - ci: bump actions/delete-package-versions from 4 to 5 (#3713) - Replace tortoise library with tortoise311 (#3697 - @brianmay) - build(deps): bump follow-redirects from 1.15.4 to 1.15.6 in /website (#3743) +- feat: experimental nix flake (#3485 - @brianmay) #### Dashboards diff --git a/assets/package-lock.json b/assets/package-lock.json index df31cdb467..83e098262c 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -25,9 +25,17 @@ "sass": "^1.63.3" } }, - "../deps/phoenix": {}, - "../deps/phoenix_html": {}, - "../deps/phoenix_live_view": {}, + "../deps/phoenix": { + "version": "1.6.16", + "license": "MIT" + }, + "../deps/phoenix_html": { + "version": "3.3.3" + }, + "../deps/phoenix_live_view": { + "version": "0.17.14", + "license": "MIT" + }, "node_modules/@creativebulma/bulma-divider": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@creativebulma/bulma-divider/-/bulma-divider-1.1.0.tgz", diff --git a/config/runtime.exs b/config/runtime.exs index 72a827bd46..95661e3c8a 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -169,3 +169,5 @@ end config :teslamate, :srtm_cache, System.get_env("SRTM_CACHE", ".srtm_cache") config :teslamate, TeslaMate.Vault, key: Util.get_env("ENCRYPTION_KEY", test: "secret") + +config :tzdata, :data_dir, System.get_env("TZDATA_DIR", "/tmp") diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..7d93f02d05 --- /dev/null +++ b/flake.lock @@ -0,0 +1,253 @@ +{ + "nodes": { + "devenv": { + "inputs": { + "flake-compat": "flake-compat", + "nix": "nix", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1688058187, + "narHash": "sha256-ipDcc7qrucpJ0+0eYNlwnE+ISTcq4m03qW+CWUshRXI=", + "owner": "cachix", + "repo": "devenv", + "rev": "c8778e3dc30eb9043e218aaa3861d42d4992de77", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "v0.6.3", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1676545802, + "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "owner": "domenkozar", + "repo": "nix", + "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "relaxed-flakes", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1678875422, + "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1707092692, + "narHash": "sha256-ZbHsm+mGk/izkWtT4xwwqz38fdlwu7nUUKXTOmm4SyE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "faf912b086576fd1a15fca610166c98d47bc667e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1686050334, + "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + } + }, + "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/flake.nix b/flake.nix new file mode 100644 index 0000000000..b6ae5d3db3 --- /dev/null +++ b/flake.nix @@ -0,0 +1,153 @@ +{ + description = "TeslaMate Logger"; + + inputs = { + nixpkgs = { url = "github:NixOS/nixpkgs/nixos-unstable"; }; + flake-utils = { url = "github:numtide/flake-utils"; }; + # See https://github.com/cachix/devenv/issues/756 + devenv.url = "github:cachix/devenv/v0.6.3"; + }; + + outputs = inputs@{ self, nixpkgs, flake-utils, devenv }: + flake-utils.lib.eachDefaultSystem (system: + let + inherit (pkgs.lib) optional optionals; + pkgs = nixpkgs.legacyPackages.${system}; + + elixir = pkgs.beam.packages.erlang.elixir_1_16; + beamPackages = pkgs.beam.packagesWith pkgs.beam.interpreters.erlang; + + src = ./.; + version = "0.0.0"; + pname = "teslamate"; + + mixFodDeps = beamPackages.fetchMixDeps { + TOP_SRC = src; + pname = "${pname}-mix-deps"; + inherit src version; + hash = "sha256-CeGtWKLjZJsoHk+uSAIz8s46XyGJWa3ECm5rSRfqlrc="; + # hash = pkgs.lib.fakeHash; + }; + + nodejs = pkgs.nodejs; + nodePackages = pkgs.buildNpmPackage { + name = "teslamate"; + src = ./assets; + npmDepsHash = "sha256-05AKPyms4WP8MHBqWMup8VXR3a1tv/f/7jT8c6EpWBw="; + # npmDepsHash = pkgs.lib.fakeHash; + dontNpmBuild = true; + inherit nodejs; + + installPhase = '' + mkdir $out + cp -r node_modules $out + ln -s $out/node_modules/.bin $out/bin + + rm $out/node_modules/phoenix + ln -s ${mixFodDeps}/phoenix $out/node_modules + + rm $out/node_modules/phoenix_html + ln -s ${mixFodDeps}/phoenix_html $out/node_modules + + rm $out/node_modules/phoenix_live_view + ln -s ${mixFodDeps}/phoenix_live_view $out/node_modules + ''; + }; + + cldr = pkgs.fetchFromGitHub { + owner = "elixir-cldr"; + repo = "cldr"; + rev = "v2.37.5"; + sha256 = "sha256-T5Qvuo+xPwpgBsqHNZYnTCA4loToeBn1LKTMsDcCdYs="; + # sha256 = pkgs.lib.fakeHash; + }; + + pkg = beamPackages.mixRelease { + TOP_SRC = src; + inherit pname version elixir src mixFodDeps; + + LOCALES = "${cldr}/priv/cldr"; + + postBuild = '' + ln -sf ${mixFodDeps}/deps deps + ln -sf ${nodePackages}/node_modules assets/node_modules + export PATH="${pkgs.nodejs}/bin:${nodePackages}/bin:$PATH" + ${nodejs}/bin/npm run deploy --prefix ./assets + + # for external task you need a workaround for the no deps check flag + # https://github.com/phoenixframework/phoenix/issues/2690 + mix do deps.loadpaths --no-deps-check, phx.digest + mix phx.digest --no-deps-check + ''; + + }; + + postgres_port = 7000; + mosquitto_port = 7001; + + psql = pkgs.writeShellScriptBin "teslamate_psql" '' + exec "${pkgs.postgresql}/bin/psql" --host "$DATABASE_HOST" --user "$DATABASE_USER" --port "$DATABASE_PORT" "$DATABASE_NAME" "$@" + ''; + mosquitto_sub = pkgs.writeShellScriptBin "teslamate_sub" '' + exec "${pkgs.mosquitto}/bin/mosquitto_sub" -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USERNAME" -P "$MQTT_PASSWORD" "$@" + ''; + + in with pkgs; { + packages.default = pkg; + devShells.default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [{ + packages = [ + elixir + elixir_ls + glibcLocales + node2nix + nodejs + prefetch-npm-deps + # for dashboard scripts + jq + psql + mosquitto + mosquitto_sub + ] ++ optional stdenv.isLinux inotify-tools + ++ optional stdenv.isDarwin terminal-notifier + ++ optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [ + CoreFoundation + CoreServices + ]); + enterShell = '' + # kludge for https://github.com/cachix/devenv/issues/862 + # export PKG_CONFIG_PATH_FOR_TARGET="$PKG_CONFIG_PATH" + export LOCALES="${cldr}/priv/cldr"; + export PORT="4000" + export ENCRYPTION_KEY="your_secure_encryption_key_here" + export DATABASE_USER="teslamate" + export DATABASE_PASS="your_secure_password_here" + export DATABASE_NAME="teslamate" + export DATABASE_HOST="127.0.0.1" + export DATABASE_PORT="${toString postgres_port}" + export MQTT_HOST="127.0.0.1" + export MQTT_PORT="${toString mosquitto_port}" + export RELEASE_COOKIE="1234567890123456789" + export TZDATA_DIR="$PWD/tzdata" + ''; + processes.mqtt = { + exec = + "${pkgs.mosquitto}/bin/mosquitto -p ${toString mosquitto_port}"; + }; + services.postgres = { + enable = true; + package = pkgs.postgresql_15; + listen_addresses = "127.0.0.1"; + port = postgres_port; + initialDatabases = [{ name = "teslamate"; }]; + initialScript = '' + CREATE USER teslamate with encrypted password 'your_secure_password_here'; + GRANT ALL PRIVILEGES ON DATABASE teslamate TO teslamate; + ALTER USER teslamate WITH SUPERUSER; + ''; + }; + }]; + }; + }); +} diff --git a/lib/teslamate_web/cldr.ex b/lib/teslamate_web/cldr.ex index 356d772a01..4cb0937094 100644 --- a/lib/teslamate_web/cldr.ex +++ b/lib/teslamate_web/cldr.ex @@ -5,5 +5,7 @@ defmodule TeslaMateWeb.Cldr do otp_app: :teslamate, providers: [], generate_docs: false, - force_locale_download: Mix.env() == :prod and System.get_env("SKIP_LOCALE_DOWNLOAD") != "true" + force_locale_download: + Mix.env() == :prod and System.get_env("SKIP_LOCALE_DOWNLOAD") != "true", + data_dir: System.get_env("LOCALES") end