From a2780915bb835ea3854c024fa89bbc4b011b4a6c Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Thu, 30 Jul 2026 00:10:34 +0200 Subject: [PATCH] Install nodejs in the builder image and fix a flaky intersection test Two CI fixes. The builder image lacked nodejs, so every job died at the first step with "exec: node: executable file not found in $PATH" (exit 127). actions/checkout and actions/cache are JavaScript actions: the runner execs node inside the job container to run them, so the image needs it even though the build itself does not. Verified by exec'ing node with no shell, which is how the runner invokes it, and by pulling the pushed image back from the registry. TwoExplicitLists_IntersectToTheCommonLibraries compared a sorted actual against an unsorted hardcoded expected, so it only passed when the randomly generated library GUIDs happened to sort that way - it failed about half of all runs and would have made CI intermittently red. The intersection is a set, so it now asserts on membership and count rather than ordering. Confirmed with 10 consecutive clean runs, up from ~50%. --- Dockerfile.builder | 6 ++++++ Jellyfin.Plugin.WatchedTogether.Tests/LibraryAccessTests.cs | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Dockerfile.builder b/Dockerfile.builder index f1bb8dd..d16e240 100644 --- a/Dockerfile.builder +++ b/Dockerfile.builder @@ -5,12 +5,18 @@ FROM mcr.microsoft.com/dotnet/sdk:9.0 +# nodejs is required by the runner itself, not by the build: actions/checkout and +# actions/cache are JavaScript actions, and the runner execs `node` inside this +# container to run them. Without it every job fails at the checkout step with +# "exec: node: executable file not found in $PATH". RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ git \ jq \ curl \ + nodejs \ + npm \ && rm -rf /var/lib/apt/lists/* RUN pip install --break-system-packages jprm diff --git a/Jellyfin.Plugin.WatchedTogether.Tests/LibraryAccessTests.cs b/Jellyfin.Plugin.WatchedTogether.Tests/LibraryAccessTests.cs index 6f60b0a..df73a18 100644 --- a/Jellyfin.Plugin.WatchedTogether.Tests/LibraryAccessTests.cs +++ b/Jellyfin.Plugin.WatchedTogether.Tests/LibraryAccessTests.cs @@ -78,7 +78,11 @@ public class LibraryAccessTests var result = service.ComputeIntersection([alice.Id, bob.Id]); - Assert.Equal([Shows, Kids], result.OrderBy(g => g).ToList().OrderBy(g => g).ToList()); + // The intersection is a set: assert on membership, not on ordering. The library ids are + // random GUIDs, so any order-sensitive assertion would pass or fail by luck of the draw. + Assert.Equal(2, result.Count); + Assert.Contains(Shows, result); + Assert.Contains(Kids, result); Assert.DoesNotContain(Movies, result); Assert.DoesNotContain(Adult, result); }