From 23e78e9a9c3ca584869c253643a3f268b7135ddb Mon Sep 17 00:00:00 2001 From: Bradley Nelson Date: Tue, 16 Jun 2026 13:51:51 -0600 Subject: [PATCH] Devenv --- .envrc | 7 ++ .gitignore | 5 + devenv.nix | 58 +++++++++ flake.lock | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 55 ++++++++ 5 files changed, 483 insertions(+) create mode 100644 .envrc create mode 100644 devenv.nix create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..e926d27e --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM=" +fi + +export DEVENV_ROOT="$PWD" + +use flake "path:$PWD" --no-pure-eval --impure diff --git a/.gitignore b/.gitignore index 905f8a95..9dc7a3d6 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,8 @@ tests/e2e/playwright/.auth/ # Test fixtures generated on-the-fly by tests/api/run.sh tests/fixtures/chunk-over-cap-*.bin wasm/oxicloud-hash/target/ + +# devenv / direnv +.devenv/ +.direnv/ +.devenv-state/ diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 00000000..89711562 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,58 @@ +{ pkgs, lib, config, ... }: + +{ + languages.rust = { + enable = true; + channel = "stable"; # edition 2024 needs a recent stable (CLAUDE.md: Rust 1.93+) + components = [ "rustc" "cargo" "clippy" "rustfmt" "rust-analyzer" "rust-src" ]; + }; + + # Native build deps + the full justfile toolchain. + packages = with pkgs; [ + pkg-config + openssl + git + + # task runner + Rust extras + just + cargo-audit + + # frontend tooling (no root package.json — these are expected as global bins) + nodejs_22 + biome + typescript # provides `tsc` + stylelint + + # helper scripts (tools/check-icons.py, tools/check-missing-translations.py) + python3 + + # API/WebDAV functional tests + the DB-readiness probe in tests/common/spawn-db.sh + hurl + netcat-gnu # provides `nc` + ]; + + # Dev Postgres on :5432, matching DATABASE_URL in example.env + # (postgres://postgres:postgres@localhost:5432/oxicloud). + services.postgres = { + enable = true; + listen_addresses = "127.0.0.1"; + port = 5432; + initialDatabases = [ { name = "oxicloud"; } ]; + # devenv's bootstrap superuser is the OS user with trust auth, so the + # password is not actually checked — but the `postgres` role must exist + # for the DATABASE_URL above to connect. Extensions per CLAUDE.md. + initialScript = '' + CREATE ROLE postgres SUPERUSER LOGIN PASSWORD 'postgres'; + \connect oxicloud + CREATE EXTENSION IF NOT EXISTS pg_trgm; + CREATE EXTENSION IF NOT EXISTS ltree; + ''; + }; + + # Load .env (justfile uses `set dotenv-load`); contributor should `cp example.env .env`. + dotenv.enable = true; + + enterShell = '' + echo "OxiCloud dev env — Rust $(rustc --version | cut -d' ' -f2), Node $(node --version), Postgres on :5432" + ''; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..a391db4d --- /dev/null +++ b/flake.lock @@ -0,0 +1,358 @@ +{ + "nodes": { + "cachix": { + "inputs": { + "devenv": [ + "devenv" + ], + "flake-compat": [ + "devenv", + "flake-compat" + ], + "git-hooks": [ + "devenv", + "git-hooks" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1777487137, + "narHash": "sha256-TuvKVBX60mqyMT6OB5JqVEh1YIWtFMR/igLCaCdC9tw=", + "owner": "cachix", + "repo": "cachix", + "rev": "a66a440c321d35f7193472c317f42a55ccd1cb93", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "latest", + "repo": "cachix", + "type": "github" + } + }, + "crate2nix": { + "flake": false, + "locked": { + "lastModified": 1772186516, + "narHash": "sha256-8s28pzmQ6TOIUzznwFibtW1CMieMUl1rYJIxoQYor58=", + "owner": "rossng", + "repo": "crate2nix", + "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e", + "type": "github" + }, + "original": { + "owner": "rossng", + "repo": "crate2nix", + "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "crate2nix": "crate2nix", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", + "ghostty": "ghostty", + "git-hooks": "git-hooks", + "nix": "nix", + "nixd": "nixd", + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1781627264, + "narHash": "sha256-TPj5d5MUyvuQZjsfDAAoYJ0SB+tNNNBrdCpD8XL0WeU=", + "owner": "cachix", + "repo": "devenv", + "rev": "0fe5629a2955141c336b95e384e2c793c01214fb", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "ghostty": { + "flake": false, + "locked": { + "lastModified": 1779069789, + "narHash": "sha256-ojo+gso45/6CVSuqfSVnlWpQ4d0QeLgwok+v/g3yu0E=", + "owner": "ghostty-org", + "repo": "ghostty", + "rev": "4b7bf0b20e3baf9c1ba10c63f2ad1fd853faea8f", + "type": "github" + }, + "original": { + "owner": "ghostty-org", + "repo": "ghostty", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778507602, + "narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "git-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" + } + }, + "nix": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "flake-parts": [ + "devenv", + "flake-parts" + ], + "git-hooks-nix": [ + "devenv", + "git-hooks" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1779748925, + "narHash": "sha256-meIhqGC04O5VXbKSFXSQoOKp+XCq5RMnwAk1Guo0VQo=", + "owner": "cachix", + "repo": "nix", + "rev": "0bc443c8ff235c3547d09327b48aaa2ab98b15f2", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "devenv-2.34", + "repo": "nix", + "type": "github" + } + }, + "nixd": { + "inputs": { + "flake-parts": [ + "devenv", + "flake-parts" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1778381404, + "narHash": "sha256-FqhdOTA8vyoIpkHhbs2cCT7h6EWM7nsLeOYJc1ifQLE=", + "owner": "nix-community", + "repo": "nixd", + "rev": "e3e45eb76663f522e196b7f0cf34cab201db7779", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixd", + "type": "github" + } + }, + "nixpkgs": { + "inputs": { + "nixpkgs-src": "nixpkgs-src" + }, + "locked": { + "lastModified": 1781620901, + "narHash": "sha256-UF6scQlG+6lRkZBUpn/3KNavhOo5G8kDWhjVHcno8uc=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "2df109b343d3c68efd752e32a444a1d9b9f89afa", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs-src": { + "flake": false, + "locked": { + "lastModified": 1781454065, + "narHash": "sha256-d2xfDjnfRuf/xYGdu9VVRHiav/2w5hDL/5cw2TuVAXw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9eac87a12312b8f60dd52e1c6e1a265f6fc7f5fc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay_2" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1779074409, + "narHash": "sha256-6aXy8Ga41iLVM8ibddFU1O5+wYWcBGNEfZzZuL91eIc=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "2a77b5b1dc952f214e8102acdef1622b68515560", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1781580018, + "narHash": "sha256-BlTedbM77FmesD2ZqR73vhFy+y77UrhefV7IYw1pDsk=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "8bceba21a1ebea535c27c4dc723a0d5a4db9e386", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "devenv", + "nixd", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1775636079, + "narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..71061d6a --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + description = "OxiCloud development environment"; + + inputs = { + nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling"; + devenv.url = "github:cachix/devenv"; + devenv.inputs.nixpkgs.follows = "nixpkgs"; + rust-overlay.url = "github:oxalica/rust-overlay"; + rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; + }; + + nixConfig = { + extra-trusted-public-keys = [ + "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" + ]; + extra-substituters = [ + "https://devenv.cachix.org" + ]; + }; + + outputs = + { + self, + nixpkgs, + devenv, + ... + }@inputs: + let + forEachSystem = nixpkgs.lib.genAttrs [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + "x86_64-darwin" + ]; + in + { + packages = forEachSystem (system: { + devenv-up = self.devShells.${system}.default.config.procfileScript; + devenv-test = self.devShells.${system}.default.config.test; + }); + + devShells = forEachSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [ ./devenv.nix ]; + }; + } + ); + }; +}