• Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • Jenkins 2.319.3
      Git Plugin 4.10.3
      Git Client Plugin 3.11.0
      GitHub 1.34.2

      We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

      Therefor we heavily rely on the currentBuild.changeSets.

      Unfortunatly we recently discovered that builds are triggered when a force push is used (which is good) to a repository, but the changes are empty (thats not expected). This can also be seen in the corresponding UI.

      There might be other constellations where it does not work but this is one we could reproduce.

          [JENKINS-68010] Changes are empty after a force push

          Daniel Geißler created issue -
          Daniel Geißler made changes -
          Description Original: We are trying to avoid build steps as much as possible, for example skipping some build steps, when a build was triggered by a Upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered (due to GitHub Changes) when a force push is done to a repository, but the changes are empty. This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|thumbnail!

          There might be other constellations where it does not work but this is one we could reproduce.
          New: We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered (due to GitHub Changes) when a force push is done to a repository, but the changes are empty. This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|thumbnail!

          There might be other constellations where it does not work but this is one we could reproduce.
          Daniel Geißler made changes -
          Description Original: We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered (due to GitHub Changes) when a force push is done to a repository, but the changes are empty. This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|thumbnail!

          There might be other constellations where it does not work but this is one we could reproduce.
          New: We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered when a force push is used (which is good) to a repository, but the changes are empty (thats not expected). This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|thumbnail!

          There might be other constellations where it does not work but this is one we could reproduce.
          Mark Waite made changes -
          Assignee Original: Mark Waite [ markewaite ]

          Mark Waite added a comment -

          This is a known limitation of the changeset computation. It assumes that the base version of the changeset exists.

          A force push frequently deletes the base version of the changeset. Selecting a new base version of the changeset is a non-trivial exercise that would need some form of heuristic to guide it. For example, after a force push, should the changeset use the version from a build that is older than the previous build? After a force push, should the changeset show only a single commit? If so, then what about users that force push a set of changes that contain multiple commits? After a force push, should the changeset show the changes since the most recent commit that has more than one successors? Each of the rules that I can envision for selecting the comparison base for a force push will have users that see the choice as flawed.

          Mark Waite added a comment - This is a known limitation of the changeset computation. It assumes that the base version of the changeset exists. A force push frequently deletes the base version of the changeset. Selecting a new base version of the changeset is a non-trivial exercise that would need some form of heuristic to guide it. For example, after a force push, should the changeset use the version from a build that is older than the previous build? After a force push, should the changeset show only a single commit? If so, then what about users that force push a set of changes that contain multiple commits? After a force push, should the changeset show the changes since the most recent commit that has more than one successors? Each of the rules that I can envision for selecting the comparison base for a force push will have users that see the choice as flawed.

          I'd like the "Changes" UI to display the equivalent of git log X..Y (or perhaps git log --no-merges X..Y), where

          • X is the commit that was used in the previous build. If the previous build did not record a commit ID, then get the commit ID from an earlier build and add a note saying which build was used. Do not look at earlier builds in any other case.
          • Y is the commit that is being used in the current build.

          If Y does not contain all the commits of X (i.e. there was a force push, or an older build was replayed), then add a note saying so, but don't list the commits that were removed.

          Maybe someone else would see this as flawed, but this seems it would be easy to implement (although I have not tried) and would be good enough for me. However, I have only been using the "Changes" UI and not currentBuild.changeSets.

          Is the current changesets algorithm documented somewhere?

          Kalle Niemitalo added a comment - I'd like the "Changes" UI to display the equivalent of git log X..Y (or perhaps git log --no-merges X..Y ), where X is the commit that was used in the previous build. If the previous build did not record a commit ID, then get the commit ID from an earlier build and add a note saying which build was used. Do not look at earlier builds in any other case. Y is the commit that is being used in the current build. If Y does not contain all the commits of X (i.e. there was a force push, or an older build was replayed), then add a note saying so, but don't list the commits that were removed. Maybe someone else would see this as flawed, but this seems it would be easy to implement (although I have not tried) and would be good enough for me. However, I have only been using the "Changes" UI and not currentBuild.changeSets . Is the current changesets algorithm documented somewhere?

          Mark Waite added a comment -

          I'd like the "Changes" UI to display the equivalent of git log X..Y (or perhaps git log --no-merges X..Y),

          As far as I understand it, that's what it does. In the case of the force push, it is quite common that X no longer exists in the repository. When X no longer exists in the repository, git log X..Y fails

          Mark Waite added a comment - I'd like the "Changes" UI to display the equivalent of git log X..Y (or perhaps git log --no-merges X..Y), As far as I understand it, that's what it does. In the case of the force push, it is quite common that X no longer exists in the repository. When X no longer exists in the repository, git log X..Y fails
          Mark Waite made changes -
          Description Original: We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered when a force push is used (which is good) to a repository, but the changes are empty (thats not expected). This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|thumbnail!

          There might be other constellations where it does not work but this is one we could reproduce.
          New: We are trying to avoid build steps as much as possible, for example skipping some of then when a build was triggered by a upstream project but did not have any changes on its own or a commit message contained a specified string (aka [skip ci]).

          Therefor we heavily rely on the {{currentBuild.changeSets}}.

          Unfortunatly we recently discovered that builds are triggered when a force push is used (which is good) to a repository, but the changes are empty (thats not expected). This can also be seen in the corresponding UI.
           !image-2022-03-11-08-18-19-018.png|!

          There might be other constellations where it does not work but this is one we could reproduce.

          Daniel Geißler added a comment - - edited

          Because we are using GitHub Enterprise I could take a quick look at the WebHook Event that has been send and interestingly I found this information as part of the push event:

            "created": false,
            "deleted": false,
            "forced": true,
            "base_ref": null,
            "compare": "https://<url>/<org>/<repo>/compare/a5a09eb5a893...1c7eb843a13a",
          

          not sure how this can be incorporated into the ChangeLog, but wouldn't that solve the issue having to investigate the diff on the Jenkins side?
          When I open the URL in the Browser it shows me exactly the commit that has been forced.

          Actually being told that there are no changes at all (same goes for newly created branches that already have commits related to their base) is definitely more confusing than being told that Jenkins could not calculate them.

          Even without the Web event I can see these use cases where force pushes are used:

          • rebase the whole branch onto a completely different commit/branch
            • either one historic build and the rebased commit have a common ancestor then the whole history in between can be shown (actually it is the diff of the current build regarding the last one anyways)
            • or all the previous builds and their baselines are not part of the history of the current commit (e.g. first build had already changes to the base branch or rebase has been done to a older branch/release) then Jenkins has no way to find the diff and at least should point out that it's currently impossible to compute the Change Log.
          • amending the latest commit (it s actually a special case of the first one)
            • one build in the history (usually the 2nd to last build) should have the same base (although many of the changes are the same I think it's still valid to show them)

          so I think going back more than one build would at least improve the ChangeLog even though it can not work for every situation.

          Daniel Geißler added a comment - - edited Because we are using GitHub Enterprise I could take a quick look at the WebHook Event that has been send and interestingly I found this information as part of the push event: "created" : false , "deleted" : false , "forced" : true , "base_ref" : null , "compare" : "https: //<url>/<org>/<repo>/compare/a5a09eb5a893...1c7eb843a13a" , not sure how this can be incorporated into the ChangeLog, but wouldn't that solve the issue having to investigate the diff on the Jenkins side? When I open the URL in the Browser it shows me exactly the commit that has been forced. Actually being told that there are no changes at all (same goes for newly created branches that already have commits related to their base) is definitely more confusing than being told that Jenkins could not calculate them. Even without the Web event I can see these use cases where force pushes are used: rebase the whole branch onto a completely different commit/branch either one historic build and the rebased commit have a common ancestor then the whole history in between can be shown (actually it is the diff of the current build regarding the last one anyways) or all the previous builds and their baselines are not part of the history of the current commit (e.g. first build had already changes to the base branch or rebase has been done to a older branch/release) then Jenkins has no way to find the diff and at least should point out that it's currently impossible to compute the Change Log. amending the latest commit (it s actually a special case of the first one) one build in the history (usually the 2nd to last build) should have the same base (although many of the changes are the same I think it's still valid to show them) so I think going back more than one build would at least improve the ChangeLog even though it can not work for every situation.

          After a force push, if you know the previous commit ID, is it possible to git fetch the commit object from GitHub? Git generally does not allow that; there is the uploadpack.allowAnySHA1InWant configuration variable but I don't know how GitHub configures that, or whether GitHub uses an entirely different implementation.

          Bitbucket Server 5.5.0 sets uploadpack.allowReachableSHA1InWant (BSERV-8268) and it helps Jenkins after a regular push but not after a force push.

          I suppose not using lightweight checkout on the Jenkins controller could let it preserve the previous commit locally (pinned by a reflog) and then compare to that. But it would need more disk space.

          Perhaps the best that can be done is display a message that includes the commit IDs and says why Jenkins was unable to compare the commits, and lets a new method of RepositoryBrowser (javadoc) link to a comparison that might still work. But that would still not help currentBuild.changeSets at all.

          Kalle Niemitalo added a comment - After a force push, if you know the previous commit ID, is it possible to git fetch the commit object from GitHub? Git generally does not allow that; there is the uploadpack.allowAnySHA1InWant configuration variable but I don't know how GitHub configures that, or whether GitHub uses an entirely different implementation. Bitbucket Server 5.5.0 sets uploadpack.allowReachableSHA1InWant ( BSERV-8268 ) and it helps Jenkins after a regular push but not after a force push. I suppose not using lightweight checkout on the Jenkins controller could let it preserve the previous commit locally (pinned by a reflog) and then compare to that. But it would need more disk space. Perhaps the best that can be done is display a message that includes the commit IDs and says why Jenkins was unable to compare the commits, and lets a new method of RepositoryBrowser ( javadoc ) link to a comparison that might still work. But that would still not help currentBuild.changeSets at all.

            Unassigned Unassigned
            dageissl Daniel Geißler
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: