{
 "number": 35417,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35417",
 "title": "ci: isolate container test networks",
 "author": "willcl-ark",
 "author_association": "MEMBER",
 "created_at": "2026-05-29T19:54:06Z",
 "updated_at": "2026-09-02T05:44:32Z",
 "age_days": 110,
 "draft": true,
 "labels": [
  "Tests",
  "CI failed"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "3fefa9c120bcb0636e630e299361a513e0c30c40",
 "head_ref": "container-networks",
 "head_repo": "willcl-ark/bitcoin",
 "head_history": [
  {
   "t": "2026-06-02T19:55:30Z",
   "sha": "3fefa9c120bcb0636e630e299361a513e0c30c40"
  }
 ],
 "additions": 37,
 "deletions": 8,
 "changed_files": 3,
 "commit_count": 2,
 "size_bucket": "S",
 "mergeable_state": "unstable",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "fanquake",
      "url": "https://github.com/bitcoin/bitcoin/pull/35417#issuecomment-4579403644"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36121,
     "title": "fuzz: Corpus sharding in parallel runs",
     "author": "maflcko"
    }
   ]
  }
 },
 "acks_parsed": {
  "fanquake": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-05-29T20:01:11Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "fanquake",
   "maflcko"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": true,
  "mergeable_state": "unstable",
  "last_author_activity": "2026-06-02T19:56:49Z",
  "last_reviewer_activity": "2026-06-02T13:44:21Z",
  "last_reviewer": "maflcko",
  "author_silent_days": 106,
  "waiting_on_author_days": 0,
  "days_since_update": 15
 },
 "refs": {
  "mentioned": [
   35416
  ],
  "depends_on": [],
  "fixes": [
   35416
  ],
  "linked_issues": [
   {
    "number": 35416,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "ci: side-effects from #33362"
   }
  ],
  "references": [
   {
    "number": 35416,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "ci: side-effects from #33362"
   }
  ],
  "conflicts": [
   36121
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "ci/test/02_run_container.py",
  "test/functional/feature_bind_port_discover.py"
 ],
 "body": "Fixes #35416\n\nLocal CI jobs currently share Docker networks while requesting fixed\nroutable addresses. That prevents two jobs from running at the same time\nbecause the second container cannot claim the same static IPs. See\n33362.\n\nName the networks \"{container_name}-ipv[4|6]\", using a subnet based on\nthe hash of their name, so each CI job gets a separate network while the\ntests continue to see the addresses they expect.\n\nIncrement them to 11.x.x.x and 1111:2222:x to avoid hitting (existing) dangling networks on machines.\n\nOn successful runs, the networks are cleaned up. On failed runs they will remain (as they are being used by the failing container).",
 "commits": [
  {
   "sha": "ee81a469c8dd2b96222943b779a6aa71cf8a5d25",
   "date": "2026-06-02T19:55:14Z",
   "message": "ci: isolate local test networks\n\nLocal CI jobs currently share Docker networks while requesting fixed\nroutable addresses. That prevents two jobs from running at the same time\nbecause the second container cannot claim the same static IPs. See\n33362.\n\nName the networks \"{container_name}-ipv[4|6]\", using a subnet based on\nthe hash of their name, so each CI job gets a separate network while the\ntests continue to see the addresses they expect."
  },
  {
   "sha": "3fefa9c120bcb0636e630e299361a513e0c30c40",
   "date": "2026-06-02T19:55:15Z",
   "message": "ci: clean up local test networks\n\nPreviously the (single, shared) networks were left in docker after runs,\nbut with a network container this may get messy.\n\nRemove the IPv4 and IPv6 networks when the run is successful. On a\nfailed run, networks will remain dangling and need manual pruning (same\nbehaviour as previously).\n\nWe can't remove networks automagically form failed runs without first\nkilling the container (docker doesn't let you remove networks which are\nactive), which we want to avoid so we can jump in to failures."
  }
 ],
 "timeline": [
  {
   "t": "2026-05-29T19:56:09Z",
   "kind": "comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "text": "Implements one apprach from https://github.com/bitcoin/bitcoin/issues/35416#issuecomment-4578958907\n\nI tried other ways of generating deterministic networks here (we have prcedent for using 'os.getpid()`), but I think in the end this is probably the most robust idea.\n\nIMO cleaning up the networks is nicer, but I can drop that commit if it's not wanted for some reason unknown to me currently (or i can squash it).\n\nAlso open to other solutions here."
  },
  {
   "t": "2026-05-29T20:01:11Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "Concept ACK - thanks for following up here."
  },
  {
   "t": "2026-06-02T13:28:46Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": null,
   "text": "nit: Would it not be easier to spin up a single network with both subnets?"
  },
  {
   "t": "2026-06-02T13:29:25Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": null,
   "text": "nit: Instead of assigning one ip here, and the other below, why not assign both below?"
  },
  {
   "t": "2026-06-02T13:35:50Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": null,
   "text": "Why this hunk? This is verbose and only  turns a well-understood python run-time error into a harder-to-debug other runtime error?"
  },
  {
   "t": "2026-06-02T13:44:08Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "test/functional/feature_bind_port_discover.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": null,
   "text": "```suggestion\nADDR1 = os.getenv('BIND_TEST_ROUTABLE_IPV4', '1.1.1.5') # This and the address below are set in the CI environment, don't change it just here (keep them in sync).\n```\n\nMaybe change the prefix, so that it isn't tied to the CI?"
  },
  {
   "t": "2026-06-02T13:44:21Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "text": "lgtm, seems fine. Left some nits"
  },
  {
   "t": "2026-06-02T19:55:30Z",
   "kind": "force_push",
   "who": "willcl-ark",
   "commit": "3fefa9c120bcb0636e630e299361a513e0c30c40"
  },
  {
   "t": "2026-06-02T19:55:50Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": 3341531627,
   "text": "neat. done."
  },
  {
   "t": "2026-06-02T19:56:06Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": 3341535823,
   "text": "both now assigned together"
  },
  {
   "t": "2026-06-02T19:56:42Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": "ci/test/02_run_container.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": 3341578785,
   "text": "At first I had something in cleanup using it, but I dropped it, so have now dropped this too."
  },
  {
   "t": "2026-06-02T19:56:49Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": "test/functional/feature_bind_port_discover.py",
   "commit": "d23a74aa1bae39202c25ffd97891b452df25f763",
   "in_reply_to": 3341640469,
   "text": "Done"
  }
 ],
 "labels_log": [
  {
   "t": "2026-05-29T19:54:09Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-02T21:20:32Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-06-19T08:46:24Z",
   "kind": "convert_to_draft",
   "who": "DrahtBot"
  }
 ],
 "text_chars": 2866,
 "text_tokens_estimate": 716,
 "changed_paths": [
  "ci/test/02_run_container.py",
  "test/functional/feature_bind_port_discover.py",
  "test/functional/feature_bind_port_externalip.py"
 ],
 "files": [
  {
   "path": "ci/test/02_run_container.py",
   "add": 30,
   "del": 5
  },
  {
   "path": "test/functional/feature_bind_port_discover.py",
   "add": 4,
   "del": 2
  },
  {
   "path": "test/functional/feature_bind_port_externalip.py",
   "add": 3,
   "del": 1
  }
 ],
 "test_lines": 45,
 "git": {
  "head": "3fefa9c120bcb0636e630e299361a513e0c30c40",
  "head_matches_backup": true,
  "base": "10dfdd4b9fab578e43ba211325967cbc28cb6652",
  "commits": [
   {
    "sha": "ee81a469c8",
    "subject": "ci: isolate local test networks",
    "files": 3,
    "add": 34,
    "del": 8
   },
   {
    "sha": "3fefa9c120",
    "subject": "ci: clean up local test networks",
    "files": 1,
    "add": 3,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "2fe8297e9008aa88",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}