feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2
- Add flake.nix + flake.lock pinning nixpkgs-unstable - Add nix/shell.nix with PostgreSQL, Rust, Elixir LSP, pre-commit hooks - Add shell.nix flake-compat shim for non-flake nix-shell users - Bump Dockerfile to Elixir 1.20.2 / OTP 29.0.3 - Add nix.md with setup and troubleshooting docs - Gitignore Nix runtime state and generated pre-commit config Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
aa6c885683
commit
a8ecee32b0
8 changed files with 648 additions and 3 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -56,6 +56,16 @@ microwaveprop-*.tar
|
|||
# Git worktrees
|
||||
/.worktrees/
|
||||
|
||||
# Nix dev shell runtime state (local to each machine)
|
||||
.nix-postgres/
|
||||
.nix-mix/
|
||||
.nix-hex/
|
||||
.nix-services-started
|
||||
.direnv/
|
||||
|
||||
# Generated by pre-commit-hooks.nix (configuration lives in nix/shell.nix)
|
||||
.pre-commit-config.yaml
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
erlang 29.0.2
|
||||
erlang 29.0.3
|
||||
elixir 1.20.2-otp-29
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
# - codeberg.org/gmcintire/prop-base - prebuilt runtime base (see Dockerfile.base)
|
||||
# - Ex: docker.io/hexpm/elixir:1.19.5-erlang-28.4.1-debian-trixie-20260316-slim
|
||||
#
|
||||
ARG ELIXIR_VERSION=1.20.1
|
||||
ARG OTP_VERSION=29.0.2
|
||||
ARG ELIXIR_VERSION=1.20.2
|
||||
ARG OTP_VERSION=29.0.3
|
||||
ARG DEBIAN_VERSION=trixie-20260518-slim
|
||||
|
||||
ARG BUILDER_IMAGE="docker.io/hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
|
||||
|
|
|
|||
124
flake.lock
generated
Normal file
124
flake.lock
generated
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769996383,
|
||||
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1784007870,
|
||||
"narHash": "sha256-djcLt/JJphyNt4eDY9XTly+/WbCK5lqWq9lSgCmJkkQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "18b9261cb3294b6d2a06d03f96872827b8fe2698",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769939035,
|
||||
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"systems": "systems"
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
69
flake.nix
Normal file
69
flake.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
description = "Prop — Microwave propagation prediction for NTMS";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
flake-parts = {
|
||||
url = "github:hercules-ci/flake-parts";
|
||||
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
systems.url = "github:nix-systems/default";
|
||||
|
||||
pre-commit-hooks = {
|
||||
url = "github:cachix/pre-commit-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
inputs@{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-parts,
|
||||
systems,
|
||||
pre-commit-hooks,
|
||||
}:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = builtins.filter (s: s != "x86_64-darwin") (import systems);
|
||||
|
||||
perSystem =
|
||||
{
|
||||
config,
|
||||
self',
|
||||
inputs',
|
||||
pkgs,
|
||||
system,
|
||||
...
|
||||
}:
|
||||
{
|
||||
_module.args.pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
overlays = [
|
||||
# Pin Erlang 29.0.3 and Elixir 1.20.2 (matches .tool-versions)
|
||||
(final: prev: {
|
||||
erlang = prev.beam.interpreters.erlang_29;
|
||||
elixir = prev.beam.packages.erlang_29.elixir_1_20;
|
||||
beamPackages = prev.beam.packages.erlang_29.extend (
|
||||
self: super: {
|
||||
elixir = super.elixir_1_20;
|
||||
}
|
||||
);
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
# Development shell with PostgreSQL, Rust, Elixir LSP
|
||||
devShells.default = pkgs.callPackage ./nix/shell.nix {
|
||||
pre-commit-hooks = inputs.pre-commit-hooks.lib.${system};
|
||||
};
|
||||
|
||||
# Nix formatter for flake files
|
||||
formatter = pkgs.nixfmt;
|
||||
};
|
||||
};
|
||||
}
|
||||
155
nix.md
Normal file
155
nix.md
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# Nix + direnv Setup
|
||||
|
||||
This project uses [Nix flakes](https://nixos.wiki/wiki/Flakes) to provide a reproducible dev environment that activates automatically when you `cd` into the project directory. No more "works on my machine" — every dev gets the same Elixir, Erlang, Rust, and PostgreSQL.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Nix flakes** (`flake.nix`) declare every tool and library the project needs, pinned via `flake.lock`.
|
||||
2. **direnv** watches for `.envrc` and loads/unloads the environment as you enter/leave the directory.
|
||||
3. **nix-direnv** bridges the two, so `use flake` in `.envrc` triggers `nix develop`.
|
||||
|
||||
The result: `cd` into the repo and you're ready to run `mix phx.server`. `cd` out and your shell is clean. No global installs, no version conflicts, no manual setup.
|
||||
|
||||
## File Layout
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `flake.nix` | Top-level flake: pins nixpkgs, Erlang/Elixir versions, defines dev shell |
|
||||
| `flake.lock` | Locked hashes for every dependency — reproducible across machines |
|
||||
| `nix/shell.nix` | Dev shell definition: packages, env vars, PostgreSQL service scripts, pre-commit hooks |
|
||||
| `shell.nix` | Flake-compat shim so `nix-shell` works without `--extra-experimental-features flakes` |
|
||||
| `.envrc` | Contains `use flake` (gitignored — create it yourself on each machine) |
|
||||
|
||||
## One-Time Setup
|
||||
|
||||
### 1. Install Nix (multi-user)
|
||||
|
||||
```bash
|
||||
sh <(curl -L https://nixos.org/nix/install)
|
||||
```
|
||||
|
||||
Follow the prompts. The multi-user install (`--daemon`) is recommended on macOS. When it finishes, open a new terminal so the Nix daemon is running.
|
||||
|
||||
Enable flakes. Add this to `~/.config/nix/nix.conf` (create the file if needed):
|
||||
```
|
||||
experimental-features = nix-command flakes
|
||||
```
|
||||
|
||||
Verify:
|
||||
```bash
|
||||
nix --version
|
||||
nix flake --help
|
||||
```
|
||||
|
||||
### 2. Install direnv
|
||||
|
||||
```bash
|
||||
brew install direnv
|
||||
```
|
||||
|
||||
Add the direnv hook to your shell's rc file. Running `brew info direnv` will print the exact line — pick the one for your shell:
|
||||
|
||||
**fish** (`~/.config/fish/config.fish`):
|
||||
```fish
|
||||
direnv hook fish | source
|
||||
```
|
||||
|
||||
**zsh** (`~/.zshrc`):
|
||||
```zsh
|
||||
eval "$(direnv hook zsh)"
|
||||
```
|
||||
|
||||
### 3. Install nix-direnv
|
||||
|
||||
```bash
|
||||
brew install nix-direnv
|
||||
```
|
||||
|
||||
Then configure direnv to load it. Create (or append to) `~/.config/direnv/direnvrc`:
|
||||
```bash
|
||||
mkdir -p ~/.config/direnv
|
||||
cat > ~/.config/direnv/direnvrc << 'EOF'
|
||||
source "$(brew --prefix nix-direnv)/share/nix-direnv/direnvrc"
|
||||
EOF
|
||||
```
|
||||
|
||||
If you installed nix-direnv via `nix profile` instead of Homebrew, the source line is:
|
||||
```
|
||||
source $HOME/.nix-profile/share/nix-direnv/direnvrc
|
||||
```
|
||||
|
||||
### 4. Create `.envrc`
|
||||
|
||||
```bash
|
||||
echo 'use flake' > .envrc
|
||||
```
|
||||
|
||||
This is gitignored — each dev creates their own. You can add personal overrides (e.g., extra env vars) here.
|
||||
|
||||
### 5. Restart your shell
|
||||
|
||||
Open a new terminal tab or `exec $SHELL` so the direnv hook takes effect.
|
||||
|
||||
### 6. First time entering the project directory
|
||||
|
||||
```bash
|
||||
cd ~/dev/prop
|
||||
direnv allow # one-time approval — thereafter it loads automatically
|
||||
```
|
||||
|
||||
The first build may take several minutes while Nix downloads and compiles packages (Erlang, Elixir, Rust, PostgreSQL, etc.). Subsequent entries are instant — direnv caches the shell.
|
||||
|
||||
## Daily Use
|
||||
|
||||
Once set up, just `cd` into the repo. The shell activates automatically:
|
||||
|
||||
- **PostgreSQL** starts on port 5432 with `prop_dev` and `prop_test` databases created
|
||||
- **`start-services`** / **`stop-services`** commands are available to manually control PostgreSQL
|
||||
- **Mix/Hex** are sandboxed to `.nix-mix` / `.nix-hex` (doesn't pollute `~/.mix`)
|
||||
- **Pre-commit hooks** (mix format, credo, nixfmt, cargo fmt, cargo clippy) install automatically
|
||||
- **Services stop** automatically when you `cd` out of the directory
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**`direnv: error .envrc is blocked`**
|
||||
Run `direnv allow` in the project directory.
|
||||
|
||||
**`nix develop` fails with "experimental Nix feature 'nix-command' is disabled"**
|
||||
Add `experimental-features = nix-command flakes` to `~/.config/nix/nix.conf`.
|
||||
|
||||
**Empty shell, no Elixir available**
|
||||
Run `nix develop --command elixir --version` to see build output. Check for syntax errors in `flake.nix` or `nix/shell.nix`:
|
||||
```bash
|
||||
nix flake check
|
||||
```
|
||||
|
||||
**Flake can't see new or modified files**
|
||||
Nix flakes only see files tracked by git. If you added a new nix file, stage it first:
|
||||
```bash
|
||||
git add -N <file>
|
||||
```
|
||||
|
||||
**Nix build fails with a hash mismatch in `shell.nix` (flake-compat)**
|
||||
The `flake-compat` tarball hash in `shell.nix` is stale. Update it to the actual hash shown in the error message.
|
||||
|
||||
**direnv not triggering on `cd`**
|
||||
Check your shell's rc file has the hook line from step 2. Run `direnv status` in the project directory.
|
||||
|
||||
**I added a new package to `nix/shell.nix` — how do I reload?**
|
||||
direnv watches `flake.nix` and `flake.lock` for changes and rebuilds automatically. If it doesn't pick up the change, run `direnv reload`.
|
||||
|
||||
## Updating Dependencies
|
||||
|
||||
The flake pins everything via `flake.lock`. To update all inputs to their latest versions:
|
||||
|
||||
```bash
|
||||
nix flake update
|
||||
```
|
||||
|
||||
To update just nixpkgs (e.g., to get a newer Erlang/Elixir):
|
||||
|
||||
```bash
|
||||
nix flake lock --update-input nixpkgs
|
||||
```
|
||||
|
||||
Commit the updated `flake.lock` so everyone gets the same versions.
|
||||
280
nix/shell.nix
Normal file
280
nix/shell.nix
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
mkShell,
|
||||
writeShellScriptBin,
|
||||
# Elixir/Erlang
|
||||
elixir,
|
||||
# Database
|
||||
postgresql_16,
|
||||
# Rust toolchain
|
||||
rustup,
|
||||
rust-analyzer,
|
||||
# Development tools
|
||||
git-lfs,
|
||||
inotify-tools,
|
||||
# LSPs and formatters
|
||||
elixir-ls,
|
||||
nixfmt,
|
||||
shellcheck,
|
||||
# Pre-commit hooks
|
||||
pre-commit-hooks,
|
||||
}:
|
||||
|
||||
let
|
||||
# PostgreSQL data directory (local to project)
|
||||
pgDataDir = ".nix-postgres";
|
||||
pgPort = "5432";
|
||||
pgHost = "localhost";
|
||||
|
||||
# Service management flag
|
||||
servicesFlag = ".nix-services-started";
|
||||
|
||||
# Script to start PostgreSQL
|
||||
startServices = writeShellScriptBin "start-services" ''
|
||||
set -e
|
||||
|
||||
echo "Starting development services..."
|
||||
|
||||
# Check if already started
|
||||
if [ -f "${servicesFlag}" ]; then
|
||||
echo "Services already running (remove ${servicesFlag} to force restart)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Initialize PostgreSQL if needed
|
||||
if [ ! -d "${pgDataDir}" ]; then
|
||||
echo "Initializing PostgreSQL database..."
|
||||
${postgresql_16}/bin/initdb -D ${pgDataDir} -U $USER --encoding=UTF8 --locale=en_US.UTF-8
|
||||
|
||||
# Configure PostgreSQL for development (fast but unsafe for production)
|
||||
cat >> ${pgDataDir}/postgresql.conf << EOF
|
||||
# Development configuration
|
||||
max_connections = 100
|
||||
shared_buffers = 128MB
|
||||
fsync = off
|
||||
synchronous_commit = off
|
||||
full_page_writes = off
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Check if PostgreSQL is already running on this port
|
||||
if ${postgresql_16}/bin/pg_isready -h ${pgHost} -p ${pgPort} > /dev/null 2>&1; then
|
||||
echo "PostgreSQL already running on port ${pgPort}"
|
||||
else
|
||||
# Start PostgreSQL
|
||||
echo "Starting PostgreSQL on port ${pgPort}..."
|
||||
${postgresql_16}/bin/pg_ctl -D ${pgDataDir} -l ${pgDataDir}/logfile -o "-p ${pgPort}" start
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
for i in {1..30}; do
|
||||
if ${postgresql_16}/bin/pg_isready -h ${pgHost} -p ${pgPort} > /dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo "PostgreSQL failed to start within 30 seconds"
|
||||
echo "Check ${pgDataDir}/logfile for details"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "PostgreSQL started successfully"
|
||||
fi
|
||||
|
||||
# Create postgres role if it doesn't exist (needed by some tools)
|
||||
${postgresql_16}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -tc \
|
||||
"SELECT 1 FROM pg_roles WHERE rolname='postgres'" | grep -q 1 || \
|
||||
${postgresql_16}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -c \
|
||||
"CREATE ROLE postgres WITH SUPERUSER LOGIN;"
|
||||
|
||||
# Create development and test databases
|
||||
for db in prop_dev prop_test; do
|
||||
${postgresql_16}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -tc \
|
||||
"SELECT 1 FROM pg_database WHERE datname='$db'" | grep -q 1 || \
|
||||
${postgresql_16}/bin/createdb -h ${pgHost} -p ${pgPort} -U $USER $db
|
||||
done
|
||||
|
||||
# Mark services as started
|
||||
touch ${servicesFlag}
|
||||
|
||||
echo ""
|
||||
echo "Development environment ready!"
|
||||
echo ""
|
||||
echo "PostgreSQL: ${pgHost}:${pgPort} (databases: prop_dev, prop_test)"
|
||||
echo ""
|
||||
'';
|
||||
|
||||
# Script to stop PostgreSQL
|
||||
stopServices = writeShellScriptBin "stop-services" ''
|
||||
set -e
|
||||
|
||||
echo "Stopping development services..."
|
||||
|
||||
# Stop PostgreSQL
|
||||
if [ -d "${pgDataDir}" ]; then
|
||||
${postgresql_16}/bin/pg_ctl -D ${pgDataDir} stop -m fast 2>/dev/null || true
|
||||
echo "PostgreSQL stopped"
|
||||
fi
|
||||
|
||||
# Remove services flag
|
||||
rm -f ${servicesFlag}
|
||||
|
||||
echo "Services stopped successfully"
|
||||
'';
|
||||
|
||||
# Pre-commit hooks configuration
|
||||
pre-commit-check = pre-commit-hooks.run {
|
||||
src = ../.;
|
||||
hooks = {
|
||||
# Elixir formatting
|
||||
mix-format = {
|
||||
enable = true;
|
||||
name = "mix format";
|
||||
entry = "mix format --check-formatted";
|
||||
files = "\\.(ex|exs)$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
|
||||
# Credo linting
|
||||
credo = {
|
||||
enable = true;
|
||||
name = "credo";
|
||||
entry = "mix credo --strict";
|
||||
files = "\\.(ex|exs)$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
|
||||
# Rust formatting and linting
|
||||
cargo-fmt = {
|
||||
enable = true;
|
||||
name = "cargo fmt";
|
||||
entry = "cargo fmt --all --check";
|
||||
files = "\\.rs$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
|
||||
cargo-clippy = {
|
||||
enable = true;
|
||||
name = "cargo clippy";
|
||||
entry = "cargo clippy --all-targets -- -D warnings";
|
||||
files = "\\.rs$";
|
||||
pass_filenames = false;
|
||||
};
|
||||
|
||||
# Nix formatting
|
||||
nixfmt = {
|
||||
enable = true;
|
||||
entry = "${nixfmt}/bin/nixfmt";
|
||||
};
|
||||
|
||||
# Shellcheck for shell scripts
|
||||
shellcheck.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
mkShell {
|
||||
name = "prop-dev";
|
||||
|
||||
# Development tools
|
||||
buildInputs = [
|
||||
# Elixir/Erlang
|
||||
elixir
|
||||
|
||||
# Database
|
||||
postgresql_16
|
||||
|
||||
# Rust toolchain
|
||||
rustup
|
||||
rust-analyzer
|
||||
|
||||
# Development tools
|
||||
git-lfs
|
||||
|
||||
# LSPs and formatters
|
||||
elixir-ls
|
||||
nixfmt
|
||||
shellcheck
|
||||
|
||||
# Service management scripts
|
||||
startServices
|
||||
stopServices
|
||||
]
|
||||
++ lib.optionals stdenv.isLinux [
|
||||
# Linux-only tools
|
||||
inotify-tools # For Mix file watching
|
||||
];
|
||||
|
||||
# Environment variables
|
||||
shellHook = ''
|
||||
# Set Mix and Hex home to local directories (avoid polluting $HOME)
|
||||
export MIX_HOME="$PWD/.nix-mix"
|
||||
export HEX_HOME="$PWD/.nix-hex"
|
||||
mkdir -p "$MIX_HOME" "$HEX_HOME"
|
||||
|
||||
# PostgreSQL connection
|
||||
export PGHOST="${pgHost}"
|
||||
export PGPORT="${pgPort}"
|
||||
export PGUSER="$USER"
|
||||
export DATABASE_URL="ecto://$USER@${pgHost}:${pgPort}/prop_dev"
|
||||
|
||||
# Development secrets (DO NOT use in production)
|
||||
export SECRET_KEY_BASE="dev_secret_key_base_at_least_64_bytes_long_for_phoenix_to_accept_it_safely"
|
||||
export RELEASE_COOKIE="dev_release_cookie_for_distributed_erlang"
|
||||
|
||||
# Development environment
|
||||
export MIX_ENV=dev
|
||||
export PHX_HOST=localhost
|
||||
export PORT=4000
|
||||
|
||||
# Ensure Erlang can find NIF libraries
|
||||
export ERL_AFLAGS="-kernel shell_history enabled"
|
||||
|
||||
# Rust: set up stable toolchain if not already installed
|
||||
if ! rustup show active-toolchain 2>/dev/null | grep -q stable; then
|
||||
rustup default stable 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Install Hex and Rebar3 if not already installed
|
||||
mix local.hex --force --if-missing > /dev/null 2>&1
|
||||
mix local.rebar --force --if-missing > /dev/null 2>&1
|
||||
|
||||
# Auto-start services on first shell entry
|
||||
if [ ! -f "${servicesFlag}" ]; then
|
||||
${startServices}/bin/start-services
|
||||
|
||||
# Run migrations if databases exist and Mix deps are available
|
||||
if [ -d "deps" ] && mix ecto.migrate 2>/dev/null; then
|
||||
echo "Database migrations applied"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install pre-commit hooks
|
||||
${pre-commit-check.shellHook}
|
||||
|
||||
# Welcome message
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════════════════╗"
|
||||
echo "║ ║"
|
||||
echo "║ Prop — Microwave Propagation Prediction ║"
|
||||
echo "║ ║"
|
||||
echo "╚═══════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Available commands:"
|
||||
echo " mix phx.server - Start Phoenix development server"
|
||||
echo " mix test - Run test suite"
|
||||
echo " mix precommit - Run pre-commit checks (format, credo, test)"
|
||||
echo " start-services - Start PostgreSQL"
|
||||
echo " stop-services - Stop PostgreSQL"
|
||||
echo " mix ecto.reset - Reset database (drop, create, migrate, seed)"
|
||||
echo " cargo build - Build Rust crates (cd rust/prop_grid_rs)"
|
||||
echo " cargo test - Run Rust tests"
|
||||
echo ""
|
||||
echo "Services:"
|
||||
echo " PostgreSQL: ${pgHost}:${pgPort}"
|
||||
echo ""
|
||||
echo "Documentation:"
|
||||
echo " See CLAUDE.md and nix.md for more information"
|
||||
echo ""
|
||||
'';
|
||||
}
|
||||
7
shell.nix
Normal file
7
shell.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Compatibility shim for developers using `nix-shell` instead of `nix develop`
|
||||
# This file uses flake-compat to provide the development shell from flake.nix
|
||||
|
||||
(import (fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9.tar.gz";
|
||||
sha256 = "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=";
|
||||
}) { src = ./.; }).shellNix.default
|
||||
Loading…
Add table
Reference in a new issue