From 7a295a2a3b342c4592cba1993e7aec00a427e218 Mon Sep 17 00:00:00 2001 From: jackschu <31808950+jackschu@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:50:59 -0400 Subject: [PATCH] setup devshell --- flake.lock | 27 +++++++++ flake.nix | 75 +++++++++++++++++++++++ nix/devshells.nix | 150 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/devshells.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..9238f46 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1780203844, + "narHash": "sha256-K5sT4jTpGs15ADhviMKNBH38REpPf5Q6mM1+N6cArVE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b51242d7d43689db2f3be91bd05d5b24fbb469c4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-26.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..468c445 --- /dev/null +++ b/flake.nix @@ -0,0 +1,75 @@ +{ + description = "AetherList SST development shell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; + }; + + outputs = { nixpkgs, ... }: + let + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + forEachSystem = f: nixpkgs.lib.genAttrs systems (system: f system); + in + { + devShells = forEachSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + import ./nix/devshells.nix { inherit pkgs; }); + + apps = forEachSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + checkApp = pkgs.writeShellScriptBin "check" '' + set -euo pipefail + + ${pkgs.nix}/bin/nix flake check -L "$@" 2>&1 | ${pkgs.ripgrep}/bin/rg -v \ + 'patching script interpreter paths in node_modules|/nix/store node_modules|node_modules/.*: interpreter directive changed from "' + ''; + in + { + check = { + type = "app"; + program = "${checkApp}/bin/check"; + meta = { + description = "Run flake checks with noisy shebang logs filtered"; + }; + }; + }); + + checks = forEachSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + lint = pkgs.buildNpmPackage { + name = "lint-check"; + src = ./.; + npmDeps = pkgs.importNpmLock { + npmRoot = ./.; + }; + npmConfigHook = pkgs.importNpmLock.npmConfigHook; + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.autoPatchelfHook ]; + buildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.stdenv.cc.cc.lib ]; + dontNpmBuild = true; + dontAutoPatchelf = true; + buildPhase = '' + ${pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isLinux "autoPatchelf node_modules/@biomejs/"} + npx tsc --noEmit + npx @biomejs/biome lint + npx next build + + CHECK_LICENSES=1 npx next build --webpack + ''; + installPhase = '' + touch $out + ''; + }; + }); + }; +} diff --git a/nix/devshells.nix b/nix/devshells.nix new file mode 100644 index 0000000..ac28ccc --- /dev/null +++ b/nix/devshells.nix @@ -0,0 +1,150 @@ +{ pkgs }: +let + defaultAgeKeyFile = "$HOME/.config/sops/age/keys.txt"; + + commonPackages = with pkgs; [ + atproto-goat + nodejs_22 + git + jq + ]; + + secretPackages = with pkgs; [ + awscli2 + age + sops + (writeShellScriptBin "sops-edit" '' + if [ -z "''${SOPS_AGE_KEY_FILE:-}" ] && [ -f "${defaultAgeKeyFile}" ]; then + export SOPS_AGE_KEY_FILE="${defaultAgeKeyFile}" + fi + + exec ${sops}/bin/sops "$@" + '') + (writeShellScriptBin "sops-rekey" '' + if [ -z "''${SOPS_AGE_KEY_FILE:-}" ] && [ -f "${defaultAgeKeyFile}" ]; then + export SOPS_AGE_KEY_FILE="${defaultAgeKeyFile}" + fi + + exec ${sops}/bin/sops updatekeys "$@" + '') + (writeShellScriptBin "show-age-pubkey" '' + age_key_file="''${SOPS_AGE_KEY_FILE:-$HOME/.config/sops/age/keys.txt}" + if [ ! -f "$age_key_file" ]; then + echo "No age key found at $age_key_file" >&2 + exit 1 + fi + + ${gnused}/bin/sed -n 's/.*public key: \(.*\)/\1/p' "$age_key_file" + '') + ]; + + blockedSst = pkgs.writeShellScriptBin "sst" '' + blocked_subcommands="deploy remove dev" + cmd="" + skip_next=0 + + for arg in "$@"; do + if [ "$skip_next" -eq 1 ]; then + skip_next=0 + continue + fi + + if [ "$arg" = "--" ]; then + break + fi + + case "$arg" in + --stage|-s|--config|--project|--region|--role-arn|--profile) + skip_next=1 + continue + ;; + -*) + continue + ;; + *) + cmd="$arg" + break + ;; + esac + done + + for blocked in $blocked_subcommands; do + if [ "$cmd" = "$blocked" ]; then + echo "Blocked: 'sst $cmd' is disabled in nix develop .#tools" >&2 + echo "Use nix develop .#local or nix develop .#dev for deploy/remove/dev." >&2 + exit 1 + fi + done + + exec ${pkgs.nodejs_22}/bin/npx --no-install sst "$@" + ''; + + ensureNodeModules = '' + if [ ! -d "$PWD/node_modules" ]; then + echo "node_modules missing; running npm ci" + npm ci --no-audit --no-fund + fi + ''; + + stageShell = { stage }: + pkgs.mkShell { + name = "stage:${stage}"; + AWS_PROFILE = "fittedair-dev"; + SST_STAGE = stage; + TZ = "America/New_York"; + DEFAULT_TIME_ZONE = "America/New_York"; + packages = commonPackages ++ secretPackages; + + shellHook = '' + export PATH="$PWD/node_modules/.bin:$PATH" + + ${ensureNodeModules} + + if [ -z "''${SOPS_AGE_KEY_FILE:-}" ] && [ -f "$HOME/.config/sops/age/keys.txt" ]; then + export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt" + fi + + secrets_file="$PWD/secrets/$SST_STAGE.yaml" + if [ -f "$secrets_file" ]; then + tmp_env_file="$(${pkgs.coreutils}/bin/mktemp)" + if ${pkgs.sops}/bin/sops --decrypt --output-type dotenv "$secrets_file" > "$tmp_env_file"; then + set -a + . "$tmp_env_file" + set +a + echo "Loaded secrets from $secrets_file" + else + echo "Warning: failed to decrypt $secrets_file" >&2 + fi + ${pkgs.coreutils}/bin/rm -f "$tmp_env_file" + else + echo "Warning: no stage secrets file found at $secrets_file" >&2 + fi + ''; + }; +in +{ + default = stageShell { stage = "local"; }; + local = stageShell { stage = "local"; }; + staging = stageShell { stage = "staging"; }; + + tools = pkgs.mkShell { + name = "stage:tools"; + SST_STAGE = "local"; + TZ = "America/New_York"; + DEFAULT_TIME_ZONE = "America/New_York"; + packages = commonPackages ++ [ blockedSst ]; + + shellHook = '' + export PATH="$PATH:$PWD/node_modules/.bin" + + ${ensureNodeModules} + + unset AWS_PROFILE + unset AWS_ACCESS_KEY_ID + unset AWS_SECRET_ACCESS_KEY + unset AWS_SESSION_TOKEN + unset AWS_REGION + unset AWS_DEFAULT_REGION + ''; + }; +} -- 2.51.2