Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Protected Branches API support #996

Merged
merged 17 commits into from
Dec 20, 2015

Conversation

ryangribble
Copy link
Contributor

This Work-In-Progress PR adds support for the protected branches API, which is currently in PREVIEW

Notes

This is our first contribution to octokit.net so just let us know if anything isn't as desired etc... I've tried to comply with existing similar implementations, coding/comment styles, unit and integration tests and so on, so hopefully it isn't too far off the mark

Since the protected branches API is in preview, I wasn't sure if it's OK to be added, but we need this support for tooling we are writing and would rather contribute to upstream than use a local fork, unless we have to! I did notice a couple of other preview features in the codebase. I also saw that octokit.rb has implemented the protected branches functions, so hopefully this is OK

Implementation Details

At a high level the change involves:

  • Create new models for Branch Protection details
  • Add Protection element to existing Branch class
  • Existing GetBranch() and GetAllBranches() calls specify new preview accepts header so this data is returned
  • Added a new EditBranch() call, similar to other Edit() methods, that takes a BranchUpdate object specifying the protection settings/fields to change. This is Patched into the Branch object/URI as per other similar examples
  • Modified existing tests for GetBranch() and GetAllBranches() calls to handle the accepts parameter now being specified
  • Added unit and integration tests for the branch protection features, which are all passing

To Do List

  • Haven't yet looked at what is required on the Octokit.Reactive project Added new function, not sure if anything more to do?

@ryangribble ryangribble changed the title Add Protected Branches support [WIP] Add Protected Branches API support Dec 13, 2015
@shiftkey
Copy link
Member

@ryangribble welcome aboard, just had a quick look at this and it looks really good! Thanks for the hard work kicking this off!

Added new function, not sure if anything more to do?

The Octokit.Reactive project is intended to be API-equivalent to the Octokit project, but returning IObservable<T> instead of Task<T>. I think what you've done is just enough, however CI isn't kicking in so I need to look at that...

/// <summary>
/// Should this branch be protected or not
/// </summary>
public bool Enabled { get; set; }
Copy link
Member

Choose a reason for hiding this comment

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

As this is a response object, this will currently fail our checks for public setters.

For serialization purposes, protected set will work fine - but we also define ctors (like in Branch above) for scenarios where you may need to set it up in a certain way.

You can see these failures by running this from the repo root:

.\build BuildApp
.\build ConventionTests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@shiftkey
Copy link
Member

Integration tests are passing on my end 👍

@haacked how do you feel about the API design here? Anything stand out for feedback?

@ryangribble
Copy link
Contributor Author

No worries Ill fix up those protected set and parameterised ctor's shortly

Regarding API design at first (and you can see on my earlier commits) I was following the octokit.rb implementation of having ProtectBranch() and UnprotectBranch() calls, however this didnt really suit the design of octokit.net which is more focused on having an Edit() method for an entity, and passing in the xxxUpdate model object with the changes... so I re-implemented as a single EditBranch() function

@shiftkey
Copy link
Member

@ryangribble Pro Tip™: don't forget to add your work account to your GitHub profile, so those last commits are linked to your profile. Or just amend the author info and push -f to your branch.

@ryangribble
Copy link
Contributor Author

@shiftkey good catch thanks, email should be fixed now

@ryangribble
Copy link
Contributor Author

LOL so I was just testing this against our GitHub Enterprise on premises installation, and it looks like the preview API isnt actually in GitHub Enterprise version 2.4.2 (eventhough the actual Branch Protection features are). Will need to wait for Enterprise to include the API feature before we can actually use this stuff in our tooling 😄

@@ -85,6 +85,12 @@ public void ResponseModelsHaveReadOnlyCollections(Type modelType)
continue;
}

// Let's skip collections that only have a private Setter
if (property.SetMethod != null && property.SetMethod.IsPrivate)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why should collection properties with private setters be mutable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this change makes it so collection properties with private setters are NOT added to the mutable list. Otherwise convention tests were failing saying that these properties werent obeying the Response object rules

That said, this was just a possible fix that seemed to work for me... definitely looking for feedback from main contributors and can easily remove this commit if required (and try to find another way to satisfy the convention tests)

Copy link
Contributor

Choose a reason for hiding this comment

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

But this is totally out of scope for this test, and it actually makes it incorrect. This test checks that "Response Models Have Read Only Collections". Making it skip properties with private setters also makes it allow mutable collections, which defeats the test in the first place. There's already a test that checks for non-public setters.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry to jump in here before this goes further off the rails, but thanks @khellang for reminding me about the intent of this test.

ICollection<T> has the mutable Add, Remove and Clear - so even if it's a read-only property, it can be manipulated arbitrarily after the object is created. We're trying to discourage that, so we use IReadOnlyList<T> on our collections.

An example of that is CommitActivity - https://github.com/octokit/octokit.net/blob/master/Octokit/Models/Response/CommitActivity.cs - if we could update RequiredStatusChecks.Contexts to be a more specific interface than ICollection<T> and then drop this change we should be able to get back to a green build...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Roger that, I'm the first to admit I haven't quite dealt with this many convention tests etc before, I was definitely hacking my way to success 😀

I'll see what I can do with the Contexts collection and ditch this incorrect convention test modification

@ryangribble
Copy link
Contributor Author

RequiredStatusChecks.Context is now an IReadonlyList, implemented as per CommitActivity example
Removed convention test hack

Also rebased on latest master

@ryangribble
Copy link
Contributor Author

Unsure about the AppVeyor test failure. All unit tests are passing for me locally?

@shiftkey
Copy link
Member

@ryangribble that test seems to be rather flaky 😞

@ryangribble
Copy link
Contributor Author

Looks like the rerun tests all passed etc

Is there anything further needed from me?

@@ -502,7 +521,8 @@ public Task<Branch> GetBranch(string owner, string repositoryName, string branch
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
Ensure.ArgumentNotNullOrEmptyString(branchName, "branchName");

return ApiConnection.Get<Branch>(ApiUrls.RepoBranch(owner, repositoryName, branchName));
const string previewAcceptsHeader = "application/vnd.github.loki-preview+json";

Choose a reason for hiding this comment

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

This const string is duplicated in 3 methods. Could we declare it at the class level and use it?

Copy link
Member

Choose a reason for hiding this comment

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

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was following an example I saw in another part of the code base where the preview header was defined each time, but I can change it to a class level.

Should the unit tests use the same define or their own class level define or specify string each time?

Copy link
Member

Choose a reason for hiding this comment

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

The licenses API? Yeah, there's two usages in MiscellaneousClient which could use a bit of 💄 to tidy up at some stage.

Let's define a field on the test class which gets reused here, and then look at the other usages separately.

@shiftkey shiftkey changed the title [WIP] Add Protected Branches API support Add Protected Branches API support Dec 16, 2015
ryangribble and others added 11 commits December 19, 2015 19:58
- Create BranchProtection models
- Add Protection element to Branch model
- Adjust RepositoryClient GetBranch and GetBranches calls to set the special preview accepts header to enable Protected Branches API (currently in preview)
- Adjust tests to include preview accepts header
- Add test for Protection element
- Create BranchUpdate model
- Add ProtectBranch and UnprotectBranch calls to RepositoryClient
- Add tests
Add tests for various protected/unprotected scenarios
@ryangribble
Copy link
Contributor Author

I really dont like the idea of referring to the test projects from the implementation classes (if that's what you meant) so what Ive done is created a AcceptHeaders helper class with the preview header defined, and changed the imlpementation to use that.

The tests are left as is, as I believe it's good practice to have each test specify what it's success criteria are, rather than use some commonly defined thing (that could be changed later unaware of the implication to tests that were using it).

Ive also got a separate branch and will follow this up with a new PR (after this one is accepted) where Ive gone and cleaned up all uses of Accepts headers (eg the licenses API as well as the standard json and html payloads etc) to use the new helper class, and remove the hardcoded strings from multiple places in implementation classes. Here's the commit in question: TattsGroup@44eb171
Let's get this PR merged first though, then I'll follow up with the general Accepts Headers tidy ups for all usages...

Also rebased on latest master

@shiftkey
Copy link
Member

@ryangribble that's fine, happy to merge this in after the Travis build goes green and iterate on this further...

shiftkey added a commit that referenced this pull request Dec 20, 2015
Add Protected Branches API support
@shiftkey shiftkey merged commit a3871ef into octokit:master Dec 20, 2015
@shiftkey
Copy link
Member

Thanks @ryangribble!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants