{
 "number": 33145,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/33145",
 "title": "CI: silent merge check",
 "author": "m3dwards",
 "author_association": "CONTRIBUTOR",
 "created_at": "2025-08-06T14:53:08Z",
 "updated_at": "2026-08-27T11:02:54Z",
 "age_days": 407,
 "draft": false,
 "labels": [
  "Tests"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
 "head_ref": "250806-ci-silent-merge",
 "head_repo": "m3dwards/bitcoin",
 "head_history": [
  {
   "t": "2026-03-04T12:55:17Z",
   "sha": "358e4a62d22038731678bc8582681ee2e9b16463"
  },
  {
   "t": "2026-03-04T13:23:53Z",
   "sha": "996bd18b668ae3ba198c82b92fb098c4e11ad3d4"
  },
  {
   "t": "2026-03-04T13:27:18Z",
   "sha": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40"
  },
  {
   "t": "2026-05-20T21:57:12Z",
   "sha": "d1ac08f1cc14c20c4b58b4738c7cfb5e9f94cab4"
  },
  {
   "t": "2026-05-20T22:09:09Z",
   "sha": "0165078fbe0d57962df03adf741a0d5b0df86020"
  },
  {
   "t": "2026-05-28T18:52:42Z",
   "sha": "393dc8a2429ccc42c607e010a830f36c585f57cf"
  },
  {
   "t": "2026-06-17T21:31:19Z",
   "sha": "532b08366311d674aebcefc197c5c1f0f70628a6"
  },
  {
   "t": "2026-06-26T20:47:01Z",
   "sha": "ef35e6c84c42480aca859878d5f9cc20d1bac87e"
  }
 ],
 "additions": 412,
 "deletions": 0,
 "changed_files": 3,
 "commit_count": 1,
 "size_bucket": "L",
 "mergeable_state": "blocked",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "fjahr",
      "url": "https://github.com/bitcoin/bitcoin/pull/33145#issuecomment-3563843760"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "maflcko": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2025-09-04T09:43:59Z",
   "stale": false
  },
  "fjahr": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2025-11-21T16:47:32Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "0xB10C",
   "Sammie05",
   "fanquake",
   "fjahr",
   "maflcko",
   "sedited",
   "willcl-ark"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "blocked",
  "last_author_activity": "2026-07-01T15:30:09Z",
  "last_reviewer_activity": "2026-08-27T11:02:46Z",
  "last_reviewer": "sedited",
  "author_silent_days": 78,
  "waiting_on_author_days": 21,
  "days_since_update": 21
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  ".github/silent-merge-check.py",
  ".github/silent-merge-test.py",
  ".github/workflows/silent-merge-check.yml",
  ".github/workflows/silentmerge.yml"
 ],
 "body": "In this design there is a new GHA job merged into the main repo that adds check runs to each PR on whether they have a silent merge conflict or not.\n\nThe idea is that we have a job that pretty much runs 24/7 triggered every 6 hours or so and set to run for 5.5 hours, it could be set to run on a GHA runner rather than a Cirrus runner. Obviously running on a Cirrus runner (or even multiple runners) would dramatically speed up how many PRs can be checked for silent merge conflicts.\n\nThe job uses the Github checks API to add a passing or failing test run to each PR directly. The silent merge check job itself should always pass, it writes pass or fail checks to the PRs.\n\nIt will look through all open PRs and discard anything that has a git merge failure or a failing test with the thinking that there is no point checking something that can't be merged anyway. Then it will select PRs that have not had a silent merge check and one by one pull the merge branch of the PR and the full CI job \"Previous releases\" on that branch.\n\nWhen all PRs have been checked it will then re-check a PR that was checked the longest time ago.",
 "commits": [
  {
   "sha": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
   "date": "2026-06-26T20:46:24Z",
   "message": "ci: add silent merge check\n\nAdds a periodic CI workflow that runs every 6 hours to detect silent\nmerge failures across all open PRs. For each PR, it fetches the\npre-built merge commit (pull/<n>/merge), runs a build and the tests,\nand posts the result as a check run against the PR's head SHA. PRs\nthat have never been checked are prioritised (oldest first),followed\nby those with the oldest existing check result."
  }
 ],
 "timeline": [
  {
   "t": "2025-08-06T15:09:17Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": null,
   "text": "Seems fine, but currently a vector of task names is accepted, see  `--task`  in https://github.com/maflcko/DrahtBot/blob/2038d4d541b89bf2601614b5656d7d30d73e17be/rerun_ci/src/main.rs#L7-L23\n\nIt would be good to allow the same somehow?"
  },
  {
   "t": "2025-08-06T19:54:22Z",
   "kind": "comment",
   "who": "Sammie05",
   "assoc": "NONE",
   "text": "Nice work on this! The label-based trigger for PeriodicMergeCICheck is a clean approach.\n\nOne thought  though since this is driven by label events, do we need to consider cases where multiple labels are applied at once? Would the condition still behave as expected?\n\nAlso agree with the suggestion from @maflcko  having a vector of task names could as well improve flexibility"
  },
  {
   "t": "2025-08-07T08:32:04Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "Other stuff to check would be that this works at all and doesn't just re-run an ancient commit, like https://github.com/bitcoin/bitcoin/pull/32989#issuecomment-3133536724"
  },
  {
   "t": "2025-08-07T14:26:27Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nJust ran a test to specifically test for this by updating the default (master) branch and adding and removing the label and it correctly picked an updated merge commit based on the PR merged into the updated master."
  },
  {
   "t": "2025-08-07T14:29:30Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": 2257511652,
   "text": "Can you elaborate a little more on what this would look like? Would this be different labels for different jobs? As in a label that runs the Previous Releases job and a different label that would run a different job?"
  },
  {
   "t": "2025-08-07T14:40:46Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": 2257511652,
   "text": "I don't know. Not sure if we want to see pull requests spammed with \"added and removed\" label events (https://github.com/testing-cirrus-runners/bitcoin/pull/19#event-19014793971).\n\nGitHub doesn't make this easy and I wonder if we may want to just spin our own CI to detect silent merge conflicts."
  },
  {
   "t": "2025-08-07T14:56:30Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": 2257511652,
   "text": "To give some more context: We are now trying to add 200+ lines of code to this repo which have to be maintained, but they cause label spam, and likely aren't sufficient to achieve the goal, because the ci-failed notification will go to the one adding the label and triggering the workflow?\n\nIf so, we'd have to create a comment (or other notification) anyway. So if additional glue code is needed, we might as well handle all code externally."
  },
  {
   "t": "2025-08-08T10:41:00Z",
   "kind": "review",
   "who": "0xB10C",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "text": "Have you considered doing something like the following in `.github/workflows/ci.yml` to avoid having to maintain separate files?\n\n```yaml\nname: CI\n\non:\n  push:\n  pull_request:\n    types: [opened, reopened, synchronize, labeled]\n\njobs:\n  conditional-job:\n    if: >\n      github.event_name == 'push' ||\n      (\n        github.event_name == 'pull_request' &&\n        (\n          github.event.action == 'opened' ||\n          github.event.action == 'reopened' ||\n          github.event.action == 'synchronize' ||\n          (\n            github.event.action == 'labeled' &&\n            contains(github.event.label.name, 'PeriodicMergeCICheck')\n          )\n        )\n      )\n    runs-on: ubuntu-latest\n    steps:\n      - run: echo \"Running CI job\"\n```"
  },
  {
   "t": "2025-08-08T16:10:54Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nCould be a good shout, seems a bit of a verbose check if that has to be included in each job. I'll have a think about it. This is exactly the type of feedback that's good to consider."
  },
  {
   "t": "2025-08-08T16:14:09Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": 2257511652,
   "text": "It's a fair comment. I'll see what the ci-failed notification could look like but you could be right that this approach is less than ideal. @0xB10C has suggested perhaps merging this into the main CI file but might come with a verbose predicate before each job."
  },
  {
   "t": "2025-08-20T15:32:53Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silentmerge.yml",
   "commit": "1b5747233faedb5ba24c8c2ec37e3b44f9a3fb62",
   "in_reply_to": 2257511652,
   "text": "Yeah, merging this with the main CI file is certainly better, if possible. However, it still leaves the issue of label spam. Also, it needs to be confirmed to be working correctly (to send the failed-notification to the right person)"
  },
  {
   "t": "2025-09-04T09:43:59Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "concept ack, but I don't have the slightest idea if this is even possible (or how) with GHA"
  },
  {
   "t": "2025-09-04T13:26:33Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "Currently working on an alternative approach of one job that loops through PRs, might close this PR in favour of the other one based on feedback."
  },
  {
   "t": "2025-10-16T07:29:45Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "Any updates here? Just asking, because it is a bit tedious to manually search for all silent merge conflicts. Example ref: https://github.com/bitcoin/bitcoin/pull/29136#issuecomment-3409544132"
  },
  {
   "t": "2025-11-21T16:47:32Z",
   "kind": "comment",
   "who": "fjahr",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK"
  },
  {
   "t": "2025-11-21T16:52:52Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "I think what could work (hacky, untested):\n\n* Setup a separate \"silent-merge-check\" repo with the desired ci config\n* Push the selected ci runs to it on the desired schedule\n* Get the result, and on failure, pass it back to the upstream repo"
  },
  {
   "t": "2026-02-13T11:40:11Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "@m3dwards are you still working on something here? My understanding is that this is still an issue."
  },
  {
   "t": "2026-02-16T16:21:04Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "I haven't been working on it but happy to pick this back up"
  },
  {
   "t": "2026-03-04T12:55:17Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "358e4a62d22038731678bc8582681ee2e9b16463"
  },
  {
   "t": "2026-03-04T13:17:43Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "I wanted to share my current direction and thinking on this and have pushed some example code and can show some test runs on my fork. I think it's a good point to get some feedback if we think this is a good general direction.\n\nIn this design there is a new GHA job merged into the main repo that adds check runs to each PR on whether they have a silent merge conflict or not.\n\nThe idea is that we have a job that pretty much runs 24/7 triggered every 6 hours or so and set to run for 5.5 hours, it could be set to run on a GHA runner rather than a Cirrus runner. Obviously running on a Cirrus runner (or even multiple runners) would dramatically speed up how many PRs can be checked for silent merge conflicts.\n\nThe job uses the Github checks API to add a passing or failing test run to each PR directly. The silent merge check job itself should always pass, it writes pass or fail checks to the PRs.\n\nIt will look through all open PRs and discard anything that has a git merge failure or a failing test with the thinking that there is no point checking something that can't be merged anyway. Then it will select PRs that have not had a silent merge check and one by one pull the merge branch of the PR and the full CI job \"Previous releases\" on that branch.\n\nWhen all PRs have been checked it will then re-check a PR that was checked the longest time ago.\n\nThings that can be tweaked:\n\n- Could run on multiple runners simultaneously rather than just one\n- How long the job is allowed to run for (currently 5.5 hours, GHA runners have a limit of 6)\n- How frequently the job is triggered\n- What type of runner to run the job on\n- The ordering of how to select the next PR to check.\n- What things trigger the job to skip a PR (currently failing tests and merge conflicts)\n\nSome back of the envelope maths with the \"Previous Releases\" job taking 10/15 minutes with a primed cache on a Cirrus runner and 300 open mergeable PRs (probably overestimate) the job would be checking each PR roughly every 4 days.\n\nPlease see a run of the job on my fork here: https://github.com/m3dwards/bitcoin/actions/runs/22670080789\nA PR that passed the silent merge check: https://github.com/m3dwards/bitcoin/pull/6\nA PR that failed the silent merge check: https://github.com/m3dwards/bitcoin/pull/5\n(I modified my master branch to have a change that would silently fail against that PR)\n\nThis is what a failing check would look like in the PR:\n\n@willcl-ark @maflcko interested in your opinion on this design and if it's worth pursuing further and polishing up."
  },
  {
   "t": "2026-03-04T13:23:53Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "996bd18b668ae3ba198c82b92fb098c4e11ad3d4"
  },
  {
   "t": "2026-03-04T13:27:18Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40"
  },
  {
   "t": "2026-05-06T07:41:40Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
   "in_reply_to": null,
   "text": "nit: Forgot to set the timeout to 6h for this task?"
  },
  {
   "t": "2026-05-06T07:41:55Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "text": "lgtm, thx!"
  },
  {
   "t": "2026-05-06T07:57:42Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "in_reply_to": null,
   "text": "should this not be `    - cron: \"0 */6 * * *\"`?"
  },
  {
   "t": "2026-05-06T08:05:14Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "in_reply_to": 3193866662,
   "text": "Most likely, definitely the intention was to run every 6 hours for 5.5 hours."
  },
  {
   "t": "2026-05-06T08:12:12Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-check.py",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "in_reply_to": null,
   "text": "nit: I think this could even be 3 hours (with a timeout and cron of 6 hours), to get a pull re-run every week, which should be enough?"
  },
  {
   "t": "2026-05-06T09:31:29Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "in_reply_to": 3193866662,
   "text": "Actually, an odd minute may be better to avoid the peak time around minute 0:\n\n`    - cron: \"37 */6 * * *\"`"
  },
  {
   "t": "2026-05-20T14:49:20Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "are you still working on this?"
  },
  {
   "t": "2026-05-20T14:58:43Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nyep, was waiting until the new CI provider was picked and merged but I guess there isn't any dependency there."
  },
  {
   "t": "2026-05-20T15:05:37Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "Yeah, this `runs-on: ubuntu-latest` (GHA), so there shouldn't be any blocker"
  },
  {
   "t": "2026-05-20T16:11:32Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "ef3ea7636ea94aa77b08cd8fb1bca078dc7d2c40",
   "in_reply_to": 3193866662,
   "text": "https://www.upworthy.com/pick-a-random-number-between-100-you-probably-chose-37-and-there-s-a-big-reason-for-that/"
  },
  {
   "t": "2026-05-20T16:21:05Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "More concerned with the cache actions changing but can deal with that if and when it happens."
  },
  {
   "t": "2026-05-20T21:57:12Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "d1ac08f1cc14c20c4b58b4738c7cfb5e9f94cab4"
  },
  {
   "t": "2026-05-20T22:09:09Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020"
  },
  {
   "t": "2026-05-21T09:57:47Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020",
   "in_reply_to": null,
   "text": "I think running the entire job with this permission would let a PR do some annoying things on GH as they have an authenticated write token to play with in run_all.sh?\n\nProbably should just have this token in a seperate step or job where it's needed"
  },
  {
   "t": "2026-05-21T09:58:38Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-check.py",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020",
   "in_reply_to": null,
   "text": "Is this intentional? surely we'd want here\n\n```\ntimedelta(hours=5, minutes=30)\n```\n\nor read from an env var (from the main workflow)"
  },
  {
   "t": "2026-05-21T10:05:30Z",
   "kind": "review_comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-test.py",
   "commit": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
   "in_reply_to": null,
   "text": "Even though these have a `mergable` field, I think it's bunk :( :\n\n```fish\ncore/worktrees/pr-33145 on \ue0a0 pr-33145 [$] via \u25b3 v4.1.2 via \ud83d\udc0d v3.13.12 via \u2744\ufe0f  impure (nix-shell-env) took 57s\n\u276f gh api 'repos/bitcoin/bitcoin/pulls/35342' --jq '{number, mergeable, mergeable_state, keys: (keys | map(select(test(\"merge\"))))}'\n{\n  \"keys\": [\n    \"auto_merge\",\n    \"merge_commit_sha\",\n    \"mergeable\",\n    \"mergeable_state\",\n    \"merged\",\n    \"merged_at\",\n    \"merged_by\"\n  ],\n  \"mergeable\": true,\n  \"mergeable_state\": \"blocked\",\n  \"number\": 35342\n}\n\ncore/worktrees/pr-33145 on \ue0a0 pr-33145 [$] via \u25b3 v4.1.2 via \ud83d\udc0d v3.13.12 via \u2744\ufe0f  impure (nix-shell-env)\n\u276f gh api 'repos/bitcoin/bitcoin/pulls?state=open&per_page=1' --jq '.[0] | {number, mergeable, mergeable_state, keys: (keys | map(select(test(\"merge\"))))}'\n{\n  \"keys\": [\n    \"auto_merge\",\n    \"merge_commit_sha\",\n    \"merged_at\"\n  ],\n  \"mergeable\": null,\n  \"mergeable_state\": null,\n  \"number\": 35342\n}\n```\n\nperhaps we need to iterate each pr individually"
  },
  {
   "t": "2026-05-21T10:07:03Z",
   "kind": "review",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020",
   "text": "I feel like I've forgotten context here (sorry), but why can this job not just do something like:\n\n- check out bitcoin/bitcoin:master\n- fetch PR head\n- attempt the merge locally\n- run a fixed build command, something like:\n\n```bash\nrm -Rf build\ncmake -B build --parallel\ncmake --build build\n\n# optionally\nctest --test-dir build\n```\n\n- publish the result?\n\nthis could probably be done on a bare runner host too, negating need for docker et al. I think it would probably be faster as well..."
  },
  {
   "t": "2026-05-21T10:18:42Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-test.py",
   "commit": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
   "in_reply_to": 3280313290,
   "text": "Jup, you'll need to call something like `get_pull_mergeable` in https://github.com/maflcko/DrahtBot/blob/6084f507bc64af4bfd5b3c33ebf725a57c66320a/rerun_ci/src/main.rs#L86"
  },
  {
   "t": "2026-05-21T10:23:23Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nYeah, if that is less code, that works, too. For reference, except for `rm -rf`, you can just call `python3 .github/ci-test-each-commit-exec.py` to do all of the cmake stuff."
  },
  {
   "t": "2026-05-21T14:58:24Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nI'm open to changing it to this but this is more code than it currently is which is simply calling `./ci/test_run_all.sh`. I also quite like the idea that it's currently running the functional tests because a failure could be logical rather than just a compilation error."
  },
  {
   "t": "2026-05-21T15:05:22Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/silent-merge-test.py",
   "commit": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
   "in_reply_to": 3280313290,
   "text": "Thanks for the heads up, that's a good catch. Will just check each PR individually, won't add much extra time."
  },
  {
   "t": "2026-05-21T15:15:32Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/silent-merge-check.py",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020",
   "in_reply_to": 3280272394,
   "text": "Yup, refactor / copy paste error."
  },
  {
   "t": "2026-05-21T15:17:57Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/workflows/silent-merge-check.yml",
   "commit": "0165078fbe0d57962df03adf741a0d5b0df86020",
   "in_reply_to": 3280266762,
   "text": "I'll have a think about this as you are right, the PR authors code will have access to the checks write token."
  },
  {
   "t": "2026-05-21T15:33:27Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\n`.github/ci-test-each-commit-exec.py` does run them, see the prior comment."
  },
  {
   "t": "2026-05-21T15:39:01Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nI'm not really understanding the advantages of this over `./ci/test_run_all.sh`. We don't want to check each commit with this job, only the merge commit right?"
  },
  {
   "t": "2026-05-21T15:47:54Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "The benefit would be that it doesn't require docker, so I think the three `uses: ./.github/actions` can be dropped. `.github/ci-test-each-commit-exec.py` only tests a single commit, the name can be changed, if needed.\n\nBut either way is fine. It should be trivial to adjust later, if needed."
  },
  {
   "t": "2026-05-27T05:22:54Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThis was fixed in https://github.com/bitcoin/bitcoin/pull/35348"
  },
  {
   "t": "2026-05-28T18:52:42Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "393dc8a2429ccc42c607e010a830f36c585f57cf"
  },
  {
   "t": "2026-05-28T18:54:51Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "Pushed latest changes to show direction. Running a bunch of tests on my fork. Will switch this PR to ready to review when the local testing is complete. It's just a bit time consuming as you have to do multiple full CI runs on a bunch of fake PRs."
  },
  {
   "t": "2026-06-17T21:31:19Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6"
  },
  {
   "t": "2026-06-18T07:45:41Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": null,
   "text": "Just checked my rerun_ci.sh script, and realized I was also running `--task 'lint'`. lint should be fast, so it could also be run here?"
  },
  {
   "t": "2026-06-18T07:46:06Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "text": "This is still in Draft. What is the status here?"
  },
  {
   "t": "2026-06-18T14:55:45Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nI think pretty much ready for review. I'm still running some tests in the background and I can add the lint job you mentioned."
  },
  {
   "t": "2026-06-18T15:49:33Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": 3434049258,
   "text": "Do you have a link to that script? To run lint as it is in `ci.yml` would require pulling docker in right and all the docker caches etc etc."
  },
  {
   "t": "2026-06-18T16:00:04Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": 3434049258,
   "text": "Well the script is  https://github.com/maflcko/DrahtBot/blob/2038d4d541b89bf2601614b5656d7d30d73e17be/rerun_ci/src/main.rs#L15\n\nI think you can just call `ci/lint.py`, because docker is already installed and docker has a built-in cache that works out of the box without having to pull anything?"
  },
  {
   "t": "2026-06-18T21:19:16Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": 3434049258,
   "text": "I've run experiments today adding lint and it dramatically slowed down how long per PR it takes to process. Right now it's shockingly fast at about 5-7 minutes per PR with a warm ccache. Adding lint took this to 35 minutes per PR. I did expect the first one to be slower but expected the second PR checked to be faster as the image would already have been built?\n\nI think I'm of the mind to just leave lint out as I wouldn't expect a silent merge issue to be often caught by the lint checker and it just slows things down and adds more complexity.\n\nThat said, if you are keen to have it, I can keep working to try and figure out why it's so slow and if we can do better caching etc.\n\nJust for reference here is a 2 PR run that was done with lint (1 hour 16 minutes): https://github.com/m3dwards/bitcoin/actions/runs/27784000378\n\nAnd one done without lint (23 minutes): https://github.com/m3dwards/bitcoin/actions/runs/27787578648"
  },
  {
   "t": "2026-06-19T10:12:08Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": 3434049258,
   "text": "Ok, fair to leave it for later.\n\nAlso, looking at the logs, it could be a bit tedious to find the failure, as it is hidden in the middle of a long log? Also, there are no timestamps on any of the lines at all?\n\nProbably fine, but maybe the CDash instance can be used to submit each result, so that each result is stand-alone?"
  },
  {
   "t": "2026-06-19T10:17:13Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "text": "lgtm. Seems fine to put the code in this repo and call it inside this CI. An alternative would be to have the code under DrahtBot and run it there."
  },
  {
   "t": "2026-06-22T18:09:41Z",
   "kind": "review_comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "path": ".github/silent-merge-test.py",
   "commit": "532b08366311d674aebcefc197c5c1f0f70628a6",
   "in_reply_to": 3434049258,
   "text": "I can add timestamps.\n\nThe logs are only printed when a PR fails but if multiple PRs fail which I would think would be unlikely then yes you would have to differentiate between the PRs and search for your PR number in the log output. I don't think this is very likely though as silent merge issues should be rare-ish?\n\nIs that good enough for this PR as it's probably mostly the same as existing CI.\n\nI am happy to look at adding results to CDash unless you think with only printing results when a PR fails is sufficient, or that it could be added as a followup."
  },
  {
   "t": "2026-06-26T20:47:01Z",
   "kind": "force_push",
   "who": "m3dwards",
   "commit": "ef35e6c84c42480aca859878d5f9cc20d1bac87e"
  },
  {
   "t": "2026-07-01T15:30:09Z",
   "kind": "comment",
   "who": "m3dwards",
   "assoc": "CONTRIBUTOR",
   "text": "Added timestamps to the log messages if they do not already have them (such as some of the functional test messages). Timestamps were also only added to the failure log as all other log messages are timestamped properly by GHA.\n\nThe logs are now collapsed into their own section meaning it should be much easier to find the log messages when something is wrong. For this reason and because the functional tests aren't integrated with ctest at the moment I have left out CDash integration either for a follow up or for never.\n\n@willcl-ark prototyped CDash here https://github.com/bitcoin/bitcoin/compare/master...willcl-ark:bitcoin:pr-33145 but because of the above I have chosen not to add this to this PR.\n\nExample of the logs being collapsed:"
  },
  {
   "t": "2026-08-27T11:02:46Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "CONTRIBUTOR",
   "text": "This hasn't received attention in a while. Can you take another look @willcl-ark @maflcko?"
  }
 ],
 "labels_log": [
  {
   "t": "2025-08-06T14:53:11Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  },
  {
   "t": "2025-09-03T10:37:49Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-04T13:24:23Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-04T14:41:56Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-04T16:51:52Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-20T22:09:42Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-20T23:01:25Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-06-18T14:55:52Z",
   "kind": "ready_for_review",
   "who": "m3dwards"
  }
 ],
 "text_chars": 16537,
 "text_tokens_estimate": 4134,
 "changed_paths": [
  ".github/silent-merge-report.py",
  ".github/silent-merge-test.py",
  ".github/workflows/silent-merge-check.yml"
 ],
 "files": [
  {
   "path": ".github/silent-merge-report.py",
   "add": 73,
   "del": 0
  },
  {
   "path": ".github/silent-merge-test.py",
   "add": 256,
   "del": 0
  },
  {
   "path": ".github/workflows/silent-merge-check.yml",
   "add": 83,
   "del": 0
  }
 ],
 "test_lines": 0,
 "git": {
  "head": "ef35e6c84c42480aca859878d5f9cc20d1bac87e",
  "head_matches_backup": true,
  "base": "1e169a8a6cb8ed0221042a9abbd121167ee02b29",
  "commits": [
   {
    "sha": "ef35e6c84c",
    "subject": "ci: add silent merge check",
    "files": 3,
    "add": 412,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "707124ca2ed8046a",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}