From 90f7559c45c46ae2b779323362e6cc16c2dc488e Mon Sep 17 00:00:00 2001 From: woksin Date: Thu, 13 Aug 2026 23:14:36 +0200 Subject: [PATCH 1/3] Lift the Chronicle pin to 16.30.1 Chronicle 16.30.1 restores skipping TLS certificate validation by default, so the CLI connects to a development server out of the box again and the pin at 16.19.3 has nothing left to hold back. --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b38ba10..1db7699 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,8 +6,8 @@ - - + + @@ -47,7 +47,7 @@ - + From 54745388832047e6a21162eae133ee910dac2e82 Mon Sep 17 00:00:00 2001 From: woksin Date: Thu, 13 Aug 2026 23:26:32 +0200 Subject: [PATCH 2/3] Pull the Chronicle test image before running the tests The integration fixture names its container image after the Chronicle package version, so every version bump faces a cold ~400MB pull. Testcontainers times the first start attempt out while that pull runs, and each retry then collides with the port the timed-out attempt still holds - which surfaces as 'Bind for 0.0.0.0:27018 failed: port is already allocated' and reads like a code failure. Pulling first takes the download off the start clock. --- .github/workflows/build.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a977645..cba6922 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,5 +32,17 @@ jobs: - name: Build run: dotnet build --configuration Release + # The integration fixture starts a Chronicle container whose image is named after the Chronicle + # package version, so a version bump always faces a cold ~400MB pull. Testcontainers times the first + # start attempt out while that pull is running, and every retry then collides with the port the + # timed-out attempt is still holding — surfacing as "Bind for 0.0.0.0:27018 failed: port is already + # allocated", which reads like a code failure and is not one. Pulling first takes the download off + # the start clock. + - name: Pull the Chronicle test image + run: | + VERSION=$(grep -oE 'Include="Cratis.Chronicle.Connections" Version="[^"]+"' Directory.Packages.props | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + echo "Pulling cratis/chronicle:$VERSION-development" + docker pull "cratis/chronicle:$VERSION-development" + - name: Test run: dotnet test --configuration Release From a5d02a5862f75be08ea69703d911189e08538485 Mon Sep 17 00:00:00 2001 From: woksin Date: Thu, 13 Aug 2026 23:30:59 +0200 Subject: [PATCH 3/3] Give the Chronicle container time to come up The health wait allowed fifteen seconds. Chronicle serves HTTPS about twelve seconds after start on a warm image and a fast machine, so a two-core runner had no margin - and running out of it does not report a timeout. Testcontainers retries the start ten times and the container from the timed-out attempt is still holding the published ports, so every retry fails with 'port is already allocated' and the real cause never appears in the log. --- .../ChronicleOutOfProcessFixtureWithLocalImage.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Integration/Chronicle/ChronicleOutOfProcessFixtureWithLocalImage.cs b/Integration/Chronicle/ChronicleOutOfProcessFixtureWithLocalImage.cs index acb3788..df60733 100644 --- a/Integration/Chronicle/ChronicleOutOfProcessFixtureWithLocalImage.cs +++ b/Integration/Chronicle/ChronicleOutOfProcessFixtureWithLocalImage.cs @@ -77,8 +77,14 @@ public ChronicleOutOfProcessFixtureWithLocalImage() /// protected override IContainer BuildContainer(INetwork network) { + // Two minutes rather than fifteen seconds. Chronicle serves HTTPS about twelve seconds after start on + // a warm image and a fast machine, which left no margin at all on a two-core runner - and running out + // of it does not report a timeout. Testcontainers retries the start ten times, and the container from + // the attempt that timed out is still holding the published ports, so every retry fails with + // "Bind for 0.0.0.0:27018 failed: port is already allocated" and the real cause never appears. + // Waiting longer costs nothing when the container is quick: the strategy returns as soon as it answers. var waitStrategy = Wait.ForUnixContainer() - .AddCustomWaitStrategy(new HttpsHealthWait(35000), s => s.WithTimeout(TimeSpan.FromSeconds(15))); + .AddCustomWaitStrategy(new HttpsHealthWait(35000), s => s.WithTimeout(TimeSpan.FromMinutes(2))); var builder = new ContainerBuilder(ChronicleImageName); builder = ConfigureImage(builder)