-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflake.nix
More file actions
138 lines (120 loc) · 6.33 KB
/
Copy pathflake.nix
File metadata and controls
138 lines (120 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{
description = "parolesub dev environment: `nix develop` drives local dev (backend + frontend) and CI alike";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
python = pkgs.python311;
# Native deps needed to build the Python dependency set from source
# (argon2-cffi's _cffi_backend, plus uvloop/httptools from
# uvicorn[standard]). python311 itself is already built against its
# own openssl/sqlite for the stdlib ssl/sqlite3 modules (verified via
# `python311.buildInputs`), and doesn't propagate them to consumers
# (`python311.propagatedBuildInputs` is empty) -- so only libffi
# needs to be supplied fresh here for cffi to link against.
pythonNativePkgs = with pkgs; [ python gcc pkg-config libffi ];
nodePkgs = with pkgs; [ nodejs_24 ];
# Common to every shell: git (shellHook uses it to find REPO_ROOT)
# and cacert (TLS root certs for pip/npm network access).
commonPkgs = with pkgs; [ git cacert ];
pythonVenvShellHook = ''
set -e
export SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
export REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
# The venv lives in the repo checkout at .venv (conventional, and not
# dependent on $HOME being writable by the test runner). It is
# gitignored. Guard against anything already sitting at that path
# that isn't a real venv (e.g. a leftover/corrupted directory, or a
# symlink -- `.venv` was once accidentally committed as one, which
# broke CI with `python -m venv` raising [Errno 17] File exists).
# `-e` alone is not enough here: it follows symlinks and reports
# false for a *dangling* one, so it must be paired with `-L`.
VENV_DIR="$REPO_ROOT/.venv"
if [ ! -f "$VENV_DIR/bin/activate" ]; then
if [ -e "$VENV_DIR" ] || [ -L "$VENV_DIR" ]; then
echo "[nix develop] removing stale venv placeholder at $VENV_DIR"
rm -rf "$VENV_DIR"
fi
echo "[nix develop] creating Python venv at .venv"
${python}/bin/python -m venv "$VENV_DIR"
fi
# shellcheck disable=SC1091
source "$VENV_DIR/bin/activate"
REQ_HASH_FILE="$VENV_DIR/.deps.sha256"
CURRENT_HASH="$(cat "$REPO_ROOT/requirements.txt" "$REPO_ROOT/requirements-dev.txt" "$REPO_ROOT/pyproject.toml" "$REPO_ROOT/VERSION" 2>/dev/null | sha256sum | cut -d' ' -f1)"
if [ ! -f "$REQ_HASH_FILE" ] || [ "$(cat "$REQ_HASH_FILE")" != "$CURRENT_HASH" ]; then
echo "[nix develop] installing/updating Python dependencies (requirements-dev.txt + editable package)"
pip install --quiet --upgrade pip
pip install --quiet -r "$REPO_ROOT/requirements-dev.txt"
pip install --quiet -e "$REPO_ROOT"
echo "$CURRENT_HASH" > "$REQ_HASH_FILE"
fi
set +e
'';
pythonEnv = {
# Keep venv + caches inside the repo, out of $HOME.
PIP_DISABLE_PIP_VERSION_CHECK = "1";
# greenlet (SQLAlchemy / argon2-cffi dep) loads libstdc++.so.6 at
# import time; nixpkgs' gcc does not put it on the default library
# search path, so expose it explicitly. Without this, every test
# that touches SQLAlchemy async raises:
# "the greenlet library is required to use this function.
# libstdc++.so.6: cannot open shared object file"
LD_LIBRARY_PATH = "${pkgs.gcc.cc.lib}/lib";
};
in
{
devShells = {
# Full environment: backend + frontend + service deps. Used for
# local dev and by CI's backend test job.
default = pkgs.mkShell {
name = "parolesub-dev";
packages = commonPkgs ++ pythonNativePkgs ++ nodePkgs ++ (with pkgs; [
# Media processing (used at runtime by ffmpeg-python)
ffmpeg
# Backend service dependency (mirrors docker-compose redis service)
redis
# Linter. The venv (requirements-dev.txt) also installs a pinned
# `ruff`, which takes PATH precedence once the shellHook activates
# it; this native copy guarantees `ruff` is runnable under
# `nix develop` even before the venv is bootstrapped, matching
# CI's `make lint`.
#
# NOTE: `mypy` is intentionally NOT provided natively here. The
# Nix `mypy` package wrapper injects a `PYTHONPATH` pointing at its
# own python3.13 site-packages, which is inherited by the venv's
# python3.11 and shadows the venv's pinned `mypy==1.9.0`, causing
# `ModuleNotFoundError: No module named 'librt.base64'` (the
# nix python3.13 mypy 1.20.1 crash). The venv's pinned `mypy` is
# the sole type-checker; run it via `nix develop -c mypy ...`.
ruff
]);
env = pythonEnv;
shellHook = pythonVenvShellHook + ''
echo ""
echo "parolesub dev shell ready:"
echo " python $(python --version 2>&1) ($(command -v python))"
echo " node $(node --version) ($(command -v node))"
echo " ffmpeg $(ffmpeg -version | head -n1 | cut -d' ' -f1-3)"
echo " redis $(redis-server --version)"
echo ""
echo "Backend: pytest | black audio_to_subs/ tests/ | ruff check audio_to_subs/ tests/ | mypy audio_to_subs/"
echo "Frontend: (cd frontend && npm install && npm run dev|test|build)"
echo "Redis: redis-server --daemonize yes (or podman-compose up redis)"
echo ""
'';
};
# Lean, node-only shell for frontend-only work (e.g. CI's frontend
# job) so it isn't paying for a Python venv bootstrap it never
# touches.
frontend = pkgs.mkShell {
name = "parolesub-frontend";
packages = commonPkgs ++ nodePkgs;
};
};
});
}