Morning... I'm looking to restrict people committing directly on an integration branch... so it should happen only through a merge from a feature branch.
Whether this is a good idea or not is moot at this stage, it's just about winning hearts and minds.
I'm struggling with commitService.getChangesetsBetween and traverse... basically I'm looking to check that any commit on the integration branch is a result of a merge.
There must be code floating about that does this, I have seen screenshots of a hipchat integration where it says "Charles was a naughty boy, he committed directly to the master branch". That's not entirely suitable for our regulators, so I need to find that code and formalise it a bit.
On the other hand I think in the past Jens has said this is tricky.
Community moderators have prevented the ability to post new answers.
Something like this:
protected static final String mergeBegin = "merge"; protected static final String refsHeads = "refs/heads/"; protected static final String featureBranchPrefix = "feature/"; protected static final String bugfixBranchPrefix = "bugfix/"; public boolean onReceive(@Nonnull final RepositoryHookContext context, @Nonnull final Collection<RefChange> refChanges, @Nonnull final HookResponse hookResponse) { for(RefChange refChange: refChanges) { //branches being deleted and changes to non-branch refs are ignored if (RefChangeType.DELETE == refChange.getType() || !refChange.getRefId().startsWith(refsHeads)) continue; final ChangesetsBetweenRequest request = new ChangesetsBetweenRequest.Builder(repository) .exclude(refChange.getFromHash()) //this is all 0's for RefChangeType.ADD .include(refChange.getToHash()) .build(); final Page<Changeset> cs = commitService.getChangesetsBetween(request, PageUtils.newRequest(0, 9999)); for(Changeset changeset: cs.getValues()) { //false for the new commit, true for the old ones if (!changesetIndex.isMemberOf(changeset.getId(), repository)) { final String commitMessage = changeset.getMessage(); if (commitMessage.toLowerCase().startsWith(mergeBegin.toLowerCase())) { continue; } final String branchName = refChange.getRefId().substring(Common.refsHeads.length()); if (branchName.toLowerCase().startsWith(featureBranchPrefix.toLowerCase())) { continue; } else if (branchName.toLowerCase().startsWith(bugfixBranchPrefix.toLowerCase())) { continue; } //reject push if a commit is new, not merge, not made to a feature/bugfix branch return false; } } } //accept push if no offending commit is found return true; }
Thanks... this opens up some new avenues for me.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Two more ideas that came to me over the weekend:
- Reject everything where the commit msg. does not start with "Merge" OR is a push to a branch whose name starts with "feature/" "bugfix/", etc. (I have some code similar to this, if you want.)
- If the RefChanges for the push, check for a pull request ref being deleted.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
> I have some code similar to this, if you want
Any sample code would be helpful, thanks.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think repositoryMetadataService.resolveRef (repo, changeSetId) may help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The branch permissions are a way to restrict access to certain branches to a subset of the people who can otherwise write the repo.
If your repo is set to be writeable for {A, B, C, D} and you set one rule in branch permissions, something like refs/heads/release/ allowed only for {D} then A, B, and C are going to be able to push to all branches except for refs/heads/release/* and D will be able to push anything, including merging code to refs/heads/release/* .
As far as I can tell, this is exactly what you want, isn't it?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Not really. That just makes D a bottleneck for reviews. In my case even D must work on a branch, then merge.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I just read your original question again and now I see what you want:
You want to reject all commits to certain branches, unless they come from a pull request.
Either you need to find that the commit has two parents, or perhaps you can listen for one of the PullRequest*Event events.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yeah it wasn't very clear. Really, I am hoping that @Charles will come on here and point me to that example code from the hipchat integration.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
- I think what you want could be achieved easiest with branch permissions: restrict push access to the integration branches to the people you do want to allow to merge code there.
- There are two things that are special to the merge commits, if you really want to detect those:
- By default, the commit message starts with "Merge". (This is always true, unless somebody edits the merge commit comments created by the tools by hand.)
- It has more than one parent.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It can be achieved easiest with branch permissions but I don't think it gives me what I want, which might be to allow anyone to merge to trunk from a feature branch (I'll deal with pull req approvals later). So I don't want to restrict to just some privileged few.
1) not nearly reliable enough.
2) I may want to prevent merging from a release branch too... so I need the refs of the parents.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.