From de97848c3d30215e373f4b229f842dc91745c878 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Sat, 29 Aug 2026 23:27:19 -0700 Subject: [PATCH 1/4] Find the git root from a worktree checkout, where .git is a file --- tests/src/TestLib/TH.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/src/TestLib/TH.hs b/tests/src/TestLib/TH.hs index 7eb862f3..ff96eeb7 100644 --- a/tests/src/TestLib/TH.hs +++ b/tests/src/TestLib/TH.hs @@ -11,8 +11,10 @@ import UnliftIO.Exception findGitRoot :: FilePath -> IO (Maybe FilePath) findGitRoot dir = do - let gitDir = dir ".git" - doesDirectoryExist gitDir >>= \case + let gitPath = dir ".git" + -- In a worktree or submodule checkout, .git is a file pointing at the real gitdir. + isRoot <- (||) <$> doesDirectoryExist gitPath <*> doesFileExist gitPath + case isRoot of True -> return (Just dir) False -> do let parent = takeDirectory dir From 0193bb6f8e5787b808fad6bf991bb92c709d3711 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Sat, 29 Aug 2026 23:27:19 -0700 Subject: [PATCH 2/4] Bump sandwich, and take parallel lanes instead of a semaphore Sandwich's parallelN now hands out lanes rather than a QSem, so parallelSemaphore and HasParallelSemaphore are gone. The bump also brings the fix for nodes left Running forever when a subtree is cancelled, which hangs waitForTree. --- tests/app/Spec/Tests.hs | 18 ++++-------------- tests/stack.yaml | 7 +++++++ tests/stack.yaml.lock | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/tests/app/Spec/Tests.hs b/tests/app/Spec/Tests.hs index d2c3873f..c0fec56c 100644 --- a/tests/app/Spec/Tests.hs +++ b/tests/app/Spec/Tests.hs @@ -5,7 +5,6 @@ module Spec.Tests where -import Control.Concurrent.QSem import Control.Monad import Control.Monad.Catch import Control.Monad.IO.Class @@ -28,13 +27,11 @@ tests = introduceJupyterRunner $ introduceJustBubblewrap $ introduceBootstrapNixpkgs $ - introduce' (defaultNodeOptions { nodeOptionsCreateFolder = False }) "Introduce parallel semaphore" parallelSemaphore getQSem (const $ return ()) $ + withParallelLanesFromArgs getParallelism $ $(getSpecFromFolder $ defaultGetSpecFromFolderOptions { getSpecCombiner = 'describeParallel - , getSpecIndividualSpecHooks = 'withParallelSemaphore + , getSpecIndividualSpecHooks = 'takeParallelLane }) - where - getQSem = getCommandLineOptions >>= liftIO . newQSem . getParallelism -- * Parallelism stuff @@ -43,7 +40,7 @@ getParallelism :: CommandLineOptions SpecialOptions -> Int getParallelism = optTestParallelism . optUserOptions describeParallel :: ( - MonadBaseControl IO m, MonadIO m, MonadMask m, HasParallelSemaphore context + MonadBaseControl IO m, MonadIO m, MonadMask m ) => String -> SpecFree context m () -> SpecFree context m () describeParallel s = (describe' (defaultNodeOptions { nodeOptionsRecordTime = False , nodeOptionsVisibilityThreshold = 50 })) s @@ -51,11 +48,4 @@ describeParallel s = (describe' (defaultNodeOptions { nodeOptionsRecordTime = Fa , nodeOptionsVisibilityThreshold = 125 , nodeOptionsCreateFolder = False })) -withParallelSemaphore :: forall context m. ( - MonadBaseControl IO m, MonadIO m, MonadMask m, HasParallelSemaphore context - ) => FilePath -> SpecFree context m () -> SpecFree context m () -withParallelSemaphore _ = around' (defaultNodeOptions { nodeOptionsRecordTime = False - , nodeOptionsVisibilityThreshold = 125 - , nodeOptionsCreateFolder = False }) "claim semaphore" $ \action -> do - s <- getContext parallelSemaphore - bracket_ (liftIO $ waitQSem s) (liftIO $ signalQSem s) (void action) + diff --git a/tests/stack.yaml b/tests/stack.yaml index c5a6f5b5..a3f5de3d 100644 --- a/tests/stack.yaml +++ b/tests/stack.yaml @@ -11,6 +11,13 @@ nix: system-ghc: true extra-deps: +- git: https://github.com/codedownio/sandwich.git + # master branch + commit: 71f7ac9754fe6bf6a6856cb0b774c356bb8ed02d + subdirs: + - sandwich + - sandwich-contexts + - git: https://github.com/codedownio/lsp.git # upgrade-monads-newest-jan2026 branch commit: c723f4a4fb99661c76b1356f8a839a0e266b0f32 diff --git a/tests/stack.yaml.lock b/tests/stack.yaml.lock index ad241700..656fa660 100644 --- a/tests/stack.yaml.lock +++ b/tests/stack.yaml.lock @@ -4,6 +4,32 @@ # https://docs.haskellstack.org/en/stable/topics/lock_files packages: +- completed: + commit: 71f7ac9754fe6bf6a6856cb0b774c356bb8ed02d + git: https://github.com/codedownio/sandwich.git + name: sandwich + pantry-tree: + sha256: a025fad1cfe3429e13a06e040846e9c0baee29178750ac2e9911542e83ae315d + size: 7057 + subdir: sandwich + version: 0.3.1.0 + original: + commit: 71f7ac9754fe6bf6a6856cb0b774c356bb8ed02d + git: https://github.com/codedownio/sandwich.git + subdir: sandwich +- completed: + commit: 71f7ac9754fe6bf6a6856cb0b774c356bb8ed02d + git: https://github.com/codedownio/sandwich.git + name: sandwich-contexts + pantry-tree: + sha256: 40d6a71d61001e81690af04a504a69e4be0a328f413ac239a8c1f3ed19a3bfae + size: 1849 + subdir: sandwich-contexts + version: 0.3.0.4 + original: + commit: 71f7ac9754fe6bf6a6856cb0b774c356bb8ed02d + git: https://github.com/codedownio/sandwich.git + subdir: sandwich-contexts - completed: commit: c723f4a4fb99661c76b1356f8a839a0e266b0f32 git: https://github.com/codedownio/lsp.git From 941bb338a02cd42bedf8fcead6edfa8813b33dfe Mon Sep 17 00:00:00 2001 From: thomasjm Date: Sun, 30 Aug 2026 03:59:34 -0700 Subject: [PATCH 3/4] CI: run the test suites in the same devShell that builds them The build step goes through direnv and the run step didn't, so the run step re-linked outside the shell that provides zlib and failed with 'cannot find -lz'. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45ace8ed..1dc3a528 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -166,8 +166,10 @@ jobs: export NIX_PATH=nixpkgs=$(nix run .#nixpkgsPath) export PATH=$(nix build --no-link .#stack --json | jq -r '.[0].outputs.out')/bin:$PATH + export PATH=$(nix build --no-link .#direnv --json | jq -r '.[0].outputs.out')/bin:$PATH - stack run --nix --no-nix-pure -- \ + direnv allow + direnv exec . stack run --nix --no-nix-pure -- \ --print \ --fixed-root "$TEST_ROOT" \ --markdown-summary "$GITHUB_STEP_SUMMARY" \ From 35a936fe9734d1034cf9baf3aba3e8d7a0e938f7 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Sun, 30 Aug 2026 19:33:03 -0700 Subject: [PATCH 4/4] CI: give each runner its own stack root The two macOS runners share a home, so when both build a snapshot that isn't cached yet, their ghc-pkg recaches deadlock on the snapshot's package db lock and every later job queues behind them forever. --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1dc3a528..07bf6af8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,6 +146,9 @@ jobs: run: | cd tests + # The two macOS runners share a home, and two stack builds recaching one snapshot's + # package db deadlock against each other. + export STACK_ROOT="$HOME/.stack-$RUNNER_NAME" export NIX_PATH=nixpkgs=$(nix run .#nixpkgsPath) export PATH=$(nix build --no-link .#stack --json | jq -r '.[0].outputs.out')/bin:$PATH @@ -164,6 +167,9 @@ jobs: echo "Got TEST_ROOT: $TEST_ROOT" echo TEST_ROOT="$TEST_ROOT" >> $GITHUB_ENV + # The two macOS runners share a home, and two stack builds recaching one snapshot's + # package db deadlock against each other. + export STACK_ROOT="$HOME/.stack-$RUNNER_NAME" export NIX_PATH=nixpkgs=$(nix run .#nixpkgsPath) export PATH=$(nix build --no-link .#stack --json | jq -r '.[0].outputs.out')/bin:$PATH export PATH=$(nix build --no-link .#direnv --json | jq -r '.[0].outputs.out')/bin:$PATH