diff --git a/.envrc b/.envrc index 3550a30..03bb5ed 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ +watch_file flake.nix use flake diff --git a/packages/repo-lib/lib.nix b/packages/repo-lib/lib.nix index 4244546..e92597f 100644 --- a/packages/repo-lib/lib.nix +++ b/packages/repo-lib/lib.nix @@ -415,6 +415,10 @@ let // formatting.programs; settings.formatter = { } // formatting.settings; }; + treefmtWrapper = treefmtEval.config.build.wrapper; + lefthookBinWrapper = pkgs.writeShellScript "lefthook-dumb-term" '' + exec env TERM=dumb ${lib.getExe pkgs.lefthook} "$@" + ''; normalizedLefthookConfig = normalizeLefthookConfig "lefthook config" lefthookConfig; lefthookCheck = lefthookNix.lib.${system}.run { @@ -424,7 +428,8 @@ let (parallelHookStageConfig "pre-commit") (parallelHookStageConfig "pre-push") (lib.setAttrByPath [ "pre-commit" "commands" "treefmt" ] { - run = "${treefmtEval.config.build.wrapper}/bin/treefmt --ci {staged_files}"; + run = "${treefmtWrapper}/bin/treefmt --no-cache {staged_files}"; + stage_fixed = true; }) (lib.setAttrByPath [ "pre-commit" "commands" "gitleaks" ] { run = "${pkgs.gitleaks}/bin/gitleaks protect --staged"; @@ -439,6 +444,7 @@ let ); }; selectedCheckOutputs = { + formatting-check = treefmtEval.config.build.check src; hook-check = lefthookCheck; lefthook-check = lefthookCheck; }; @@ -549,10 +555,17 @@ let in { checks = selectedCheckOutputs; - formatter = treefmtEval.config.build.wrapper; + formatter = treefmtWrapper; shell = pkgs.mkShell { + LEFTHOOK_BIN = builtins.toString lefthookBinWrapper; packages = lib.unique ( - selectedStandardPackages ++ extraPackages ++ toolPackages ++ [ pkgs.lefthook ] + selectedStandardPackages + ++ extraPackages + ++ toolPackages + ++ [ + pkgs.lefthook + treefmtWrapper + ] ); shellHook = buildShellHook { hooksShellHook = lefthookCheck.shellHook; diff --git a/template/.envrc b/template/.envrc index 3550a30..03bb5ed 100644 --- a/template/.envrc +++ b/template/.envrc @@ -1 +1,2 @@ +watch_file flake.nix use flake diff --git a/tests/release.sh b/tests/release.sh index b5fad22..6deadac 100755 --- a/tests/release.sh +++ b/tests/release.sh @@ -35,7 +35,7 @@ assert_contains() { local needle="$1" local haystack_file="$2" local message="$3" - if ! grep -Fq "$needle" "$haystack_file"; then + if ! grep -Fq -- "$needle" "$haystack_file"; then fail "$message (missing '$needle')" fi } @@ -296,6 +296,16 @@ write_mk_repo_lefthook_flake() { EOF } +init_git_repo() { + local repo_dir="$1" + + run_capture_ok "init_git_repo: git init failed" git -C "$repo_dir" init + run_capture_ok "init_git_repo: git config user.name failed" git -C "$repo_dir" config user.name "Repo Lib Test" + run_capture_ok "init_git_repo: git config user.email failed" git -C "$repo_dir" config user.email "repo-lib-test@example.com" + run_capture_ok "init_git_repo: git add failed" git -C "$repo_dir" add flake.nix + run_capture_ok "init_git_repo: git commit failed" git -C "$repo_dir" commit -m "init" +} + write_tool_failure_flake() { local repo_dir="$1" cat >"$repo_dir/flake.nix" <&2 } +run_mk_repo_treefmt_hook_case() { + local case_name="mkRepo configures treefmt and lefthook for dev shell hooks" + local workdir + workdir="$(mktemp -d)" + local repo_dir="$workdir/mk-repo-treefmt" + local system + local derivation_json="$workdir/treefmt-hook.drv.json" + local lefthook_yml_drv + local lefthook_yml_json="$workdir/treefmt-hook-yml.drv.json" + mkdir -p "$repo_dir" + write_mk_repo_flake "$repo_dir" + CURRENT_LOG="$workdir/mk-repo-treefmt.log" + + init_git_repo "$repo_dir" + + run_capture_ok "$case_name: treefmt should be available in shell" bash -c 'cd "$1" && nix develop --no-write-lock-file . -c sh -c '"'"'printf "%s\n" "$LEFTHOOK_BIN" && command -v treefmt'"'"'' _ "$repo_dir" + assert_contains 'lefthook-dumb-term' "$CURRENT_LOG" "$case_name: LEFTHOOK_BIN wrapper missing" + assert_contains '/bin/treefmt' "$CURRENT_LOG" "$case_name: treefmt missing from shell" + + system="$(nix eval --raw --impure --expr 'builtins.currentSystem')" + run_capture_ok "$case_name: formatting check derivation show failed" bash -c 'nix derivation show "$1" >"$2"' _ "$repo_dir#checks.${system}.formatting-check" "$workdir/formatting-check.drv.json" + run_capture_ok "$case_name: lefthook derivation show failed" bash -c 'nix derivation show "$1" >"$2"' _ "$repo_dir#checks.${system}.lefthook-check" "$derivation_json" + + lefthook_yml_drv="$(perl -0ne 'print "/nix/store/$1\n" if /"([a-z0-9]{32}-lefthook\.yml\.drv)"/' "$derivation_json")" + if [[ -z "$lefthook_yml_drv" ]]; then + fail "$case_name: could not locate lefthook.yml derivation" + fi + + run_capture_ok "$case_name: lefthook.yml derivation show failed" bash -c 'nix derivation show "$1" >"$2"' _ "$lefthook_yml_drv" "$lefthook_yml_json" + assert_contains '--no-cache {staged_files}' "$lefthook_yml_json" "$case_name: treefmt hook missing staged-file format command" + assert_contains '\"stage_fixed\":true' "$lefthook_yml_json" "$case_name: treefmt hook should re-stage formatted files" + + rm -rf "$workdir" + CURRENT_LOG="" + echo "[test] PASS: $case_name" >&2 +} + run_mk_repo_tool_failure_case() { local case_name="mkRepo required tools fail shell startup" local workdir @@ -1370,6 +1417,7 @@ run_version_metadata_case run_mk_repo_case run_mk_repo_command_tool_case run_mk_repo_lefthook_case +run_mk_repo_treefmt_hook_case run_mk_repo_tool_failure_case run_impure_bootstrap_validation_case run_legacy_api_eval_case