Skip to content

Support Bitbucket push webhooks that contain multiple changes #10071

@sandro-h

Description

@sandro-h
Issue Type
  • Feature enhancement
Summary

Normally, when a change is pushed to a Bitbucket repository, it issues a push webhook call with a single change element:

  "changes": [
    {
      "ref": {
        "id": "refs/heads/release/1.0",
        "displayId": "release/1.0",
        "type": "BRANCH"
      },
      "refId": "refs/heads/release/1.0",
      "fromHash": "cc3eb9e8f1c8d0a1bc4088b0fb863d0e371c178e",
      "toHash": "88dad105761a7beade0ecea5a873fa50c4a628f8",
      "type": "UPDATE"
    }
  ]

However, Bitbucket has an automatic branch merging feature, which propagates a single PR merge to multiple newer release branches. In this case, Bitbucket issues a single push webhook call with one change element for each target branch:

"changes": [
  {
    "ref": {
      "id": "refs/heads/release/1.1",
      "displayId": "release/1.1",
      "type": "BRANCH"
    },
    "refId": "refs/heads/release/1.1",
    "fromHash": "ccfeb36044ec53a2cb2ed258fcc4bf22d9d9c9c6",
    "toHash": "c3212a36f1d531b512dd6b4c9aaa19541c6256a0",
    "type": "UPDATE"
  },
  {
    "ref": {
      "id": "refs/heads/release/1.2",
      "displayId": "release/1.2",
      "type": "BRANCH"
    },
    "refId": "refs/heads/release/1.2",
    "fromHash": "4dd5ec79b362f506adf6de5084275d7bd9f8cea3",
    "toHash": "39e89ea6608f4c1293b8f03f7a3c4c8ca2b8cad6",
    "type": "UPDATE"
  },
  {
    "ref": {
      "id": "refs/heads/master",
      "displayId": "master",
      "type": "BRANCH"
    },
    "refId": "refs/heads/master",
    "fromHash": "a97d7d57257c39f2268e5ed4279be6dd99b29f8c",
    "toHash": "071e30bb9ee23a07fa82cea63f64e97a8c698f64",
    "type": "UPDATE"
  }
]

GoCD ignores all except the first change in this list:

@Override
public String branch() {
return this.changes.stream()
.filter(change -> change.ref != null)
.filter(change -> equalsIgnoreCase(change.ref.type, "branch"))
.map(change -> change.ref.displayId)
.findFirst()
.orElse(""); // if pushing a tag, this might be blank
}

Therefore, even though a change happened on the remaining branches, the corresponding branch-specific pipelines are not triggered.

Suggested feature enhancement

Adjust the webhook logic to issue a material update for each element in the changes array.

I'm happy to provide a PR for this. Here's my proposed change. Please let me know if this makes sense before I start implementing anything:

  • Modify PushPayload interface so branch() returns collection
  • Modify the implementations accordingly:
    • Return all changes in the Bitbucket implementations (probably a Set, to guard against a branch appearing twice)
    • Return a singleton collection for GitHub and Gitlab (AFAIK they always have only one change per webhook call)
  • Modify PushWebhookControllerV1.notify to call updateGitMaterial for each returned branch. This requires "merging" the response:
    • If all changes have an empty tag, return Ignoring push to non-branch.
    • If any change successfully triggers a material update, return success
    • If none of the changes trigger a material update, return No matching materials!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions