From 783e8da0c42fed9ca7b9ec69aa6255539da85660 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 18 Nov 2025 09:37:02 +0100 Subject: [PATCH 1/4] harness: add network verification after creation Add NetworkInfo call after network creation to verify the network is actually accessible before proceeding. This helps catch race conditions where Docker reports success but the network isn't fully ready yet, which can cause 'network not found' errors during container startup. This particularly helps with CI environments running tests in parallel where Docker daemon may be under heavy load. --- harness/harness.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/harness/harness.go b/harness/harness.go index 2d525db5d..4d143a3d6 100644 --- a/harness/harness.go +++ b/harness/harness.go @@ -448,6 +448,16 @@ func (h *Harness) setupDockerEnvironment() { require.NoError(h.T, err, "failed to create network") h.Logf("Docker network created: %s (id=%s)", h.network.Network.Name, h.network.Network.ID) + + // Verify network is actually accessible before proceeding. This helps + // catch race conditions where Docker reports success but the network + // isn't fully ready yet. + require.NoError(h.T, h.pool.Retry(func() error { + _, err := h.pool.Client.NetworkInfo(h.network.Network.ID) + return err + }), "failed to verify network exists") + + h.Log("Docker network verified") } // createDataDirectories creates the necessary data directories for bitcoind, From ed7de365d7303680df479c0130dd13d65d4e8820 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 18 Nov 2025 09:54:36 +0100 Subject: [PATCH 2/4] harness: remove automatic network pruning to fix race condition Remove the pruneStaleHarnessNetworks() call at startup which was causing race conditions with parallel tests: Race condition: 1. Test A creates network (no containers yet) 2. Test B starts and calls pruneStaleHarnessNetworks() 3. Test B sees Test A's network has 0 containers and deletes it 4. Test A tries to start container but network is gone --- harness/harness.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/harness/harness.go b/harness/harness.go index 4d143a3d6..f71e73887 100644 --- a/harness/harness.go +++ b/harness/harness.go @@ -56,7 +56,7 @@ const ( // networkPrefix is the prefix for private Docker networks created // for each harness instance to ensure isolation between test runs. - networkPrefix = "ark-itest-" + networkPrefix = "ark-harness-" // bitcoindRPCUser is the RPC username for bitcoind in regtest mode. bitcoindRPCUser = "admin1" @@ -440,7 +440,14 @@ func (h *Harness) setupDockerEnvironment() { h.pool, err = dockertest.NewPool("") require.NoError(h.T, err, "failed to init docker pool") - h.pruneStaleHarnessNetworks() + // Note: We used to call pruneStaleHarnessNetworks() here to clean up + // networks from previous failed runs, but it caused race conditions + // with parallel tests. Each harness now only cleans up its own + // network during shutdown. Stale networks from truly failed runs can + // be cleaned up with: docker network prune + // + // If automatic cleanup is needed, it should run with a large grace + // period (5+ minutes) to avoid interfering with active tests. // Per-run isolation. h.Log("Creating docker network...") @@ -689,8 +696,13 @@ func (h *Harness) createNetworkUnique() (*dockertest.Network, error) { return nil, lastErr } -func (h *Harness) pruneStaleHarnessNetworks() { - // Best-effort, ignore errors. +// PruneStaleHarnessNetworks performs best-effort cleanup of stale harness +// Docker networks that are empty. +// +// NOTE: This function is no longer called automatically during tests to avoid +// race conditions. It's kept here for manual cleanup if needed. +func (h *Harness) PruneStaleHarnessNetworks() { + // Best-effort cleanup of empty harness networks. nets, err := h.pool.Client.ListNetworks() if err != nil { h.Logf("[DEBUG] Failed to list networks for pruning: %v", err) From 950ec804598bf6aebda96832caf345a394d0dcd0 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 18 Nov 2025 14:02:53 +0100 Subject: [PATCH 3/4] github: retain test artifacts on unit test CI failure --- .github/workflows/main.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9f8222749..571f893fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -190,3 +190,28 @@ jobs: flag-name: 'unit' format: 'golang' parallel: true + + - name: Fix artifact permissions + if: always() + run: | + # Fix permissions for test artifacts (created in package directories) + find . -type d -name "test-artifacts" -exec sudo chown -R "$(id -u):$(id -g)" {} + || true + find . -type d -name "test-artifacts" -exec sudo chmod -R a+r {} + || true + + - name: Set artifact name + if: failure() + id: artifact-name + run: | + # Sanitize matrix.unit_type for use in artifact name + SAFE_NAME=$(echo "${{ matrix.unit_type }}" | sed 's/[^a-zA-Z0-9_-]/_/g') + echo "name=test-artifacts-${SAFE_NAME}-${{ github.run_id }}" >> $GITHUB_OUTPUT + + - name: Upload test artifacts on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: | + **/test-artifacts/ + retention-days: 5 + if-no-files-found: ignore From 2daa2c9d8cc4470cb334168306f291933a6a00cc Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 18 Nov 2025 14:04:59 +0100 Subject: [PATCH 4/4] github: disable unnecessary space cleanup to save runtime --- .github/workflows/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 571f893fd..f6bc7ee1f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,8 +44,9 @@ jobs: # Needed for some checks. fetch-depth: 0 - - name: Clean up runner space - uses: ./.github/actions/cleanup-space + # Uncomment this step if you want to enable cleanup of runner space. + #- name: Clean up runner space + # uses: ./.github/actions/cleanup-space - name: Setup Go ${{ env.GO_VERSION }} uses: ./.github/actions/setup-go