Skip to content

Conversation

@rudymatela
Copy link

@rudymatela rudymatela commented Jul 15, 2022

Partly closes: #77

Qualify the test branch by PR id in order to prepare for a future change where we will have multiple PR ids. Instead of building on testing, we build on testing/<id>.

This is made on top of #131.

Side effect

There is no side effect. GitHub only shows the following boxes when the pusher is the GitHub user. So only the user used by Hoff would see it and not regular developer users. 🎉 :-)

There is a little side effect of this, while the tests for a PR is running, GitHub will show a "compare & pull request" suggestion box:

compare-and-pull-request
compare-and-pull-request-w

It should disappear after the build passes or fails and the branch is deleted by Hoff.

Ideally, there should be a setting on GitHub to tell it to ignore branches starting with a given testing/ prefix. But it seems this is not the case. According to my (lack of) findings, there is no way to set this:

One could think of mitigating this by having a small set of testing slots for which we start by dismissing manually:

  • testing/1
  • testing/2
  • testing/3
  • testing/4
  • testing/5
  • testing/6

However, this solution would not work, because:

  • limit the maximum number of PRs in our merge train (Merge train #77);
  • make it difficult to manage in terms of code (keeping track of free slots);
  • make it difficult to know which testing branches are actually being used in case of build failures (with PR numbers it is easy!);
  • ... all of this by not actually solving the problem from the get-go -- at least in the first six builds per project we would have to manually dismiss each "compare and pull request" suggestion.

So it seems we are stuck with the minor side effect of seeing that button while the build builds.

@rudymatela rudymatela mentioned this pull request Jul 15, 2022
43 tasks
@rudymatela rudymatela changed the title Qualify the test branch by PR id Merge train: qualify the test branch by PR id Jul 15, 2022
@rudymatela rudymatela self-assigned this Jul 15, 2022
@rudymatela

This comment was marked as resolved.

@rudymatela rudymatela force-pushed the junk/merge-train/infer-integration-candidate branch from 8ad5644 to 4910759 Compare July 19, 2022 08:38
@rudymatela rudymatela force-pushed the merge-train/isolate-test-branches branch from 1d7d49e to eb849f1 Compare July 19, 2022 08:38
@rudymatela rudymatela deleted the branch master July 19, 2022 09:12
@rudymatela rudymatela closed this Jul 19, 2022
@rudymatela rudymatela reopened this Jul 19, 2022
@rudymatela rudymatela changed the base branch from merge-train/infer-integration-candidate to junk/merge-train/infer-integration-candidate July 19, 2022 09:22
@rudymatela rudymatela force-pushed the junk/merge-train/infer-integration-candidate branch from 4910759 to 9188ef9 Compare July 19, 2022 11:31
@rudymatela rudymatela force-pushed the merge-train/isolate-test-branches branch from 02f2523 to 3167ce6 Compare July 19, 2022 11:32
@rudymatela rudymatela marked this pull request as ready for review July 19, 2022 14:19
@rudymatela rudymatela requested a review from fatho July 19, 2022 14:19
@ruuda
Copy link

ruuda commented Jul 19, 2022

Qualify the test branch by PR id in order to prepare for a future change where we will have multiple PR ids

The PR id might not uniquely identify the thing you are building. Suppose we have PRs A and B, we build a train master <- A <- B, build A and B, but now A fails. Then we want to do master <- B, a different commit. I think if the strategy is to only build sequentially, and you don’t care about results of the pending builds on top of a failed build, then every pull request will occur at most once at the tip of a build, and it still works. But if you want to “hedge the bet” (e.g. build both master <- A <- B, and also master <- B, so that if A fails, then next best alternative is already in progress), a pull request can be at the tip of multiple builds.

One could think of mitigating this by having a small set of testing slots

Yeah, I think you will need this either way. The more parallel builds you speculatively start, the lower the return on investment, because the longer the train is, the more likely it is to fail. And if you don’t limit parallelism in Hoff but instead let the CI provider handle that, then priority is hard to control. I would go with the build slots, and make the amount configurable.

testing/1

Keep in mind that the branch testing and testing/1 cannot coexist, because Git tracks branches as files under .git/refs, and .git/refs/remotes/origin/testing cannot simultaneously be a file and a directory. When the naming scheme changes, it will be a one-time nuisance for all people who pull from the repository and who might have a testing (remote tracking) branch locally, and the error can be puzzling if you’re not aware of this implementation detail leak.

@rudymatela
Copy link
Author

Qualify the test branch by PR id in order to prepare for a future change where we will have multiple PR ids

The PR id might not uniquely identify the thing you are building. Suppose we have PRs A and B, we build a train master <- A <- B, build A and B, but now A fails. Then we want to do master <- B, a different commit. I think if the strategy is to only build sequentially, and you don’t care about results of the pending builds on top of a failed build, then every pull request will occur at most once at the tip of a build, and it still works. But if you want to “hedge the bet” (e.g. build both master <- A <- B, and also master <- B, so that if A fails, then next best alternative is already in progress), a pull request can be at the tip of multiple builds.

The current idea is to build only:

  • master <- A
  • master <- A <- B
  • master <- A <- B <- C

The following will only start building once A fails (and consequently B and C, since the current plan does not allow merging further PRs on top of a failing PR):

  • master <- B
  • master <- B <- C

In this way the PR id still uniquely identifies the build.

In the future, if we decide to move towards more speculative builds I would rather use testing/1-2-3 to signify three built on top of two built on top of one.

Yeah, I think you will need this either way. The more parallel builds you speculatively start, the lower the return on investment, because the longer the train is, the more likely it is to fail. And if you don’t limit parallelism in Hoff but instead let the CI provider handle that, then priority is hard to control. I would go with the build slots, and make the amount configurable.

See the idea above: testing/1-2-3.

Keep in mind that the branch testing and testing/1 cannot coexist, because Git tracks branches as files under .git/refs, and .git/refs/remotes/origin/testing cannot simultaneously be a file and a directory. When the naming scheme changes, it will be a one-time nuisance for all people who pull from the repository and who might have a testing (remote tracking) branch locally, and the error can be puzzling if you’re not aware of this implementation detail leak.

I am aware of that, the current implementation already takes this into account, see: 503461e. The testing branch is deleted before the creation of any testing/<id> branch. That's also listed in the TODO list of #77:

  • fix issue of pushing testing/<id> in the presence of testing

@rudymatela rudymatela mentioned this pull request Jul 20, 2022
21 tasks
Base automatically changed from junk/merge-train/infer-integration-candidate to master July 20, 2022 12:51
@ruuda
Copy link

ruuda commented Jul 20, 2022

The testing branch is deleted before the creation of any testing/ branch

Yes, but it will also be an issue for everybody who has cloned the repository and who has a remote-tracking branch (which is probably going to be everybody who uses that repository), it will make git fetch complain until the local ref is deleted:

$ git fetch
error: cannot lock ref 'refs/remotes/origin/testing/1': 'refs/remotes/origin/testing' exists; cannot create 'refs/remotes/origin/testing/1'
From /tmp/upstream
 ! [new branch]      testing/1  -> origin/testing/1  (unable to update local ref)

It’s nothing that an announcement can’t fix, I just wanted to point it out.

Copy link
Member

@fatho fatho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for now - But I'll have a final look once it has been rebased after the other relevant PRs have been merged.

@rudymatela rudymatela force-pushed the merge-train/isolate-test-branches branch from 273eba5 to e7880bc Compare July 27, 2022 15:22
@rudymatela
Copy link
Author

The testing branch is deleted before the creation of any testing/ branch

Yes, but it will also be an issue for everybody who has cloned the repository and who has a remote-tracking branch (which is probably going to be everybody who uses that repository), it will make git fetch complain until the local ref is deleted:

$ git fetch
error: cannot lock ref 'refs/remotes/origin/testing/1': 'refs/remotes/origin/testing' exists; cannot create 'refs/remotes/origin/testing/1'
From /tmp/upstream
 ! [new branch]      testing/1  -> origin/testing/1  (unable to update local ref)

It’s nothing that an announcement can’t fix, I just wanted to point it out.

@ruuda This makes sense, noted.

I haven't tested this, but I guess this can be (manually) fixed in two ways:

  1. git fetch --prune
  2. git branch -rd origin/testing && git fetch

I'll check whether either/both work and include these in an announcement accordingly.

@rudymatela rudymatela requested a review from fatho July 27, 2022 15:34
@rudymatela
Copy link
Author

LGTM for now - But I'll have a final look once it has been rebased after the other relevant PRs have been merged.

@fatho The other relevant PRs have been merged and I rebased on top of the new master. Can you please take a look again?

Copy link
Member

@fatho fatho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rudymatela
Copy link
Author

@fatho Thanks for the review.

I will wait until I deploy v0.25.9 before I merge this.

... this is for now ignored so there are no changes in app behaviour.

In the future, this will be used to qualify the test branch with the id of the
originating PR.
... in order to support CI parallel execution of testing branches (merge train)
@rudymatela rudymatela force-pushed the merge-train/isolate-test-branches branch from e7880bc to 746472e Compare July 28, 2022 14:09
@rudymatela
Copy link
Author

rudymatela commented Jul 28, 2022

I performed a trivial rebase on top of master which was updated with a change in 3 lines of code. There were no conflicts:

rudy@dev-lt-55:~/channable/hoff$ git l ..master
2022-07-28 10:25:34 +0200  2cd75b0  Rudy Matela  Hoff v0.25.9   (tag: v0.25.9, origin/master, origin/HEAD, master)
2022-07-28 10:01:07 +0200  8e2ec1e  OpsBotPrime  Merge #145: Ignore duplicate build status webhooks   (origin/testing)
2022-07-28 09:45:02 +0200  6017ef6  Rudy Matela  Ignore duplicate build status hooks. (fix tests)  
2022-07-28 09:42:08 +0200  fac73f9  Rudy Matela  test/Spec: test duplicate GH hooks (break tests)  

rudy@dev-lt-55:~/channable/hoff$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Pass PullRequestId to tryIntegrate
Applying: Qualify testing branch name by PullRequestId
Applying: Add (unused) DeleteBranch operation
Applying: fixup! Add (unused) DeleteBranch operation
Applying: initial version of test branch cleaning up
Applying: src/Git: rename DeleteBranch to DeleteRemoteBranch
Applying: add and use the deleteBranch operation
Applying: refactor: add and use Logic.testBranch (DRY code)
Applying: fix bug in deleteRemoteBranch
Applying: src/Logic: delete unqualified testing branch
Applying: fix failing tests: cleanup of integration branches
Applying: EventLoopSpec: add test for a failing build
Applying: fix build of tests/Spec.hs

rudy@dev-lt-55:~/channable/hoff$ git push --force-with-lease
...
To github.com:channable/hoff
 + e7880bc...746472e merge-train/isolate-test-branches -> merge-train/isolate-test-branches (forced update)

... so I don't think there's need to review again. I would let @OpsBotPrime deal with this, but I need to rebase #137 on top of this very PR, so I might as well rebase on top of something that includes the latest master commit.

@rudymatela
Copy link
Author

I tested this in conjunction with GitHub again just to be sure and all seems to be working. It's time to prepare the next deployment again. @OpsBotPrime merge on Friday.

@OpsBotPrime
Copy link

Pull request approved for merge by @rudymatela, rebasing now.

@OpsBotPrime
Copy link

Rebased as 9cbd57e, waiting for CI …

@OpsBotPrime
Copy link

@rudymatela
Copy link
Author

rudymatela commented Jul 29, 2022

Here is the message I will send to the users.

Manual intervention required for @OpsBotPrime (Hoff v0.26.0)

Hoff v0.26.0 builds PRs on separate testing branches qualified by PR# (testing/360, testing/1337, etc). After Hoff starts a testing build, you may get the following error when fetching or pulling from the remote repository:

$ git fetch
error: cannot lock ref 'refs/remotes/origin/testing/109': 'refs/remotes/origin/testing' exists; cannot create 'refs/remotes/origin/testing/109'
From github.com:organization/repository
 ! [new branch]      rudy-testing/109 -> origin/rudy-testing/109  (unable to update local ref)
error: some local refs could not be updated; try running
 'git remote prune origin' to remove any old, conflicting branches

If that happens, simply follow the instruction by git to prune the conflicting branch:

$ git remote prune origin
Pruning origin
URL: git@github.com:channable/git-sandbox
 * [pruned] origin/rudy-testing

Then pull or fetch again:

$ git fetch

Alternatively you can use git fetch --prune.

Unfortunately, this will happen once per repository. To fix the issue for all repositories that have been built by Hoff already, you can do:

$ cd <workspace>
$ for repo in *; do git -C $repo fetch --prune; done

Why is this change necessary?

A future version of Hoff will include parallel builds of a merge train (#77), this is necessary so we can support that.

@OpsBotPrime OpsBotPrime force-pushed the merge-train/isolate-test-branches branch from 746472e to 9cbd57e Compare July 29, 2022 09:57
@OpsBotPrime OpsBotPrime merged commit 9cbd57e into master Jul 29, 2022
@OpsBotPrime OpsBotPrime deleted the merge-train/isolate-test-branches branch July 29, 2022 09:57
@rudymatela rudymatela added enhancement New feature or request OKR Objectives and Key Results train Involves Merge Trains labels Aug 17, 2022
rudymatela added a commit that referenced this pull request Aug 23, 2022
In #134, we transitioned from testing on `testing/<id>` instead of just
`testing`.  In order to maintain backwards compatibility, we had to delete
`testing` every time we created a new `testing/<id>` branch.

That has been a month ago, and most projects that use Hoff should have had at
least one PR triggering the deletion of `testing`.  So we should remove this
code that tries deletion every time.

We currently see the following in the logs every time we merge:

```haskell
Aug 18 13:37:12 hoff hoff[4321]: [Warn] error: git push -d failed. Reason: error: unable to delete 'testing': remote ref does not exist
Aug 18 13:37:29 hoff hoff[4321]: error: failed to push some refs to 'git@github.com:<org>/<repo>.git'
```

This should get rid of entries like the above.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request OKR Objectives and Key Results train Involves Merge Trains

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Merge train

4 participants