mitjabezensek / sharpbucket Goto Github PK
View Code? Open in Web Editor NEWSharpBucket is a .Net wrapper for the Bitbucket's REST API.
License: MIT License
SharpBucket is a .Net wrapper for the Bitbucket's REST API.
License: MIT License
The basic testing logic has been added but now we need to write additional tests. For now at least the tests that target the publicly accessible repos. Here is an example of how they might look like.
Apart from writing additional tests also consider running the tests on the AppVeyor CI. Would need to find a way to set up the authentication info on the AppVeyor project.
I have forked the repository. What I am hoping to do is use SharpBucket on an ASP.NET site to pull contributed items for a hosted service. I would have the pull triggered once per night as an automated task to look for the latest commit, compare to my site's latest copy, and pull any updated/new files.
To do this I need to implement the [src] https://confluence.atlassian.com/display/BITBUCKET/src+Resources portion of the API v1. I tried this but it will not let me return a simple string for the base-64 encoded text due to type restrictions on the generic methods. Is there another API already implemented that does something similar? I am thinking that right now I would need to add new methods for Get, Send, etc. that would handle a string return value instead of a typed value.
Thanks,
Bryan
Is there any way to get text the pull request?
Is there a way to access the access token?
I am attempting to run clone commands and need to pass along the token.
Thanks!
var sharpBucket = new SharpBucketV2();
sharpBucket.OAuthentication2(Key,Secret)
throws
System.Exception: 'Unable to retrieve OAuth2 Token:
0
'
Any help? Thanks.
Hi,
I can't see to find any reference to projects in the API. I've looked for the following:
Do these APIs exist or am I barking up the wrong tree?
Looks to me like the properties for "TeamProfile" do not represent a team profile as described here: https://confluence.atlassian.com/display/BITBUCKET/teams+Endpoint#teamsEndpoint-GETtheteamprofile.
"TeamProfile" should probably be "TeamInfo", following the pattern in your other classes.
Surely I'm missing smt... Using V1.
Issue newIssue = new Issue();
...
newIssue.responsible = new User();
newIssue.responsible.username = bitbucketAssigneeTextBox.Text.Trim();
RepositoriesEndPoint repositoryEndPoint = ConnectToBitbucket();
IssuesResource issuesResource = repositoryEndPoint.IssuesResource();
Issue newlyOpenedIssue = issuesResource.PostIssue(newIssue);
...
the code above produces the below POST body which of course Bitbucket doesn't support
...&priority=major&reported_by=SharpBucket.V1.Pocos.User..
There used to be NewIssue, ExistingIssue POCOs. Or should I implement them myself extending Issue.
I've added some support for paging in v2, but I'm unclear how to be certain I haven't broken anything. My own use is very narrow (polling repos), so there are a lot of code paths I'm not hitting during dev. Any tips on running the tests?
I want to add in filtering, but according to this Debug.Assert(!overrideUrl.Contains("?"));
line of code, you don't seem to want filtering? Why?
using SharpBucket.V2.Pocos;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
namespace SharpBucket.V2.EndPoints
{
public class EndPoint
{
// vanilla page length in many cases is 10, requiring lots of requests for larger collections
private const int DEFAULT_PAGE_LEN = 50;
protected readonly ISharpBucketV2 _sharpBucketV2;
protected readonly string _baseUrl;
public EndPoint(ISharpBucketV2 sharpBucketV2, string resourcePath)
{
_sharpBucketV2 = sharpBucketV2;
_baseUrl = resourcePath;
}
/// <summary>
/// Generator that allows lazy access to paginated resources.
/// </summary>
/// <typeparam name="TValue"></typeparam>
/// <param name="overrideUrl"></param>
/// <param name="pageLen"></param>
/// <param name="requestParameters"></param>
/// <returns></returns>
private IEnumerable<List<TValue>> IteratePages<TValue>(string overrideUrl, int pageLen = DEFAULT_PAGE_LEN, IDictionary<string, object> requestParameters = null)
{
Debug.Assert(!String.IsNullOrEmpty(overrideUrl));
Debug.Assert(!overrideUrl.Contains("?"));
if (requestParameters == null)
{
requestParameters = new Dictionary<string, object>();
}
requestParameters["pagelen"] = pageLen;
IteratorBasedPage<TValue> response;
int page = 1;
do
{
response = _sharpBucketV2.Get(new IteratorBasedPage<TValue>(), overrideUrl.Replace(SharpBucketV2.BITBUCKET_URL, ""), requestParameters);
if (response == null)
{
break;
}
yield return response.values;
requestParameters["page"] = ++page;
}
while (!String.IsNullOrEmpty(response.next));
}
/// <summary>
/// Returns a list of paginated values.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="overrideUrl">The override URL.</param>
/// <param name="max">Set to 0 for unlimited size.</param>
/// <param name="requestParameters"></param>
/// <returns></returns>
/// <exception cref="System.Net.WebException">Thrown when the server fails to respond.</exception>
protected List<TValue> GetPaginatedValues<TValue>(string overrideUrl, int max = 0, IDictionary<string, object> requestParameters = null)
{
bool isMaxConstrained = max > 0;
int pageLen = (isMaxConstrained && max < DEFAULT_PAGE_LEN) ? max : DEFAULT_PAGE_LEN;
List<TValue> values = new List<TValue>();
foreach (var page in IteratePages<TValue>(overrideUrl, pageLen, requestParameters))
{
if (page == null)
{
break;
}
if (isMaxConstrained &&
values.Count + page.Count >= max)
{
values.AddRange(page.GetRange(0, max - values.Count));
Debug.Assert(values.Count == max);
break;
}
values.AddRange(page);
}
return values;
}
}
}
I can't find a way to filter commits using SharpBucket like I can with a direct call in the api:
https://api.bitbucket.org/2.0/repositories/{user}/{slug}/commits/{branch}?exclude=master
Is it possible to append "?exclude=master" (for example) to RepositoryResource.ListCommits?
I don't see a way to use filter or overrideUrl, when listing commits, to acheive this.
I want to retrieve commit details, how does this work?
What should I do with the object
I get?
It's also not utilized in your test project.
var sharpBucket = new SharpBucketV2();
sharpBucket.OAuth2LeggedAuthentication("", "");
var repositoryEndpoint = sharpBucket.RepositoriesEndPoint();
var repositoryResource = repositoryEndpoint.RepositoryResource("", "");
var commits = repositoryResource.ListCommits();
I also want to point out that I was confused in the first place because I used the NuGet package and tried to match the API with the code on GitHub, which wasn't possible because the versions differ.
I'd like to suggest to freeze the "productive" NuGet version in another branch at least.
What do you think?
Kind regards,
Timm
With each release we should write release notes. This is especially critical at this early state since we quite often introduce breaking changes. This should help SharpBucket users with decisions about updating to the new version.
How to list my tags with Sharp Bitbucket?
I cannot use the 2 legged OAuth1.0 authentication that is used in the console program. It seems that something was changed.
PostRepository uses the Repository.name property to populate the POST request URL.
internal Repository PutRepository(Repository repo, string accountName)
{
var overrideUrl = GetRepositoryUrl(accountName, repo.name, null);
return _sharpBucketV2.Put(repo, overrideUrl);
}
While the repository name being used in the request URL is required to be lower cased and slugified, it is not a requirement for the repository's name to be lower case or slugified. These should be two separate values.
A simple solution would be to pass _repository from RepositoryResource.cs to RepositoriesEndpoint.PostRepository, similar to how it is done with PutRepository.
internal Repository PostRepository(Repository repo, string accountName, string repository)
{
var overrideUrl = GetRepositoryUrl(accountName, repository, null);
return _sharpBucketV2.Post(repo, overrideUrl);
}
Failing to authenticate and getting a System.Net.WebException
I have checked, the response is Unauthorized from the API.
The RestClient includes the authenticator with
ConsumerKey
ConsumerSecret
Token
TokenSecret
Verifier
This should be all that is needed to authenticate and receive the token I believe.
public BitBucketController()
{
sharpbucket = new SharpBucket.V1.SharpBucketV1();
authenticator = sharpbucket.OAuth3LeggedAuthentication(BitbucketApiKey, BitbucketApiSecret, "oob");
}
public void GetPin()
{
var uri = authenticator.StartAuthentication();
Process.Start(uri);
}
public void Authenticate(string pin)
{
authenticator.AuthenticateWithPin(pin);
}
I'd like to add the summary for each commit. The JSON looks like this:
"summary": {
"raw": "[ABC-3392] a meaningful description\n",
"markup": "markdown",
"html": "<p>[<a rel=\"nofollow\" href=\"https://foo.atlassian.net/browse/ABC-3392\" target=\"_blank\" data-module-key=\"dvcs-connector-issue-key-linker\" data-link-key=\"dvcs-connector-issue-key-linker\" data-app-key=\"jira-bitbucket-connector-plugin.0277a6a4-4e3d-34e1-bab2-1c14de870122\" data-principal-uuid=\"{1b6feefd-32c1-4cb6-9e19-d662df20c277}\" class=\"ap-connect-dialog\">ABC-3392</a>] a meaningful description</p>",
"type": "rendered"
},
In a local git repo, it's only the raw
version that's useful; here the other fields show how BitBucket formats the summary for display -- in this case, it includes a link to the relevant issue in JIRA.
I'm happy to put together a PR, but should this property on Commit
be a new Summary
object, or should it just be a string
with the raw
value?
Using GetDiffForPullRequest() throws two exceptions:
{Data at the root level is invalid. Line 1, position 1."} System.Exception {System.Xml.XmlException}
and
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at SharpBucket.Authentication.Authenticate.GetResponse[T](String url, Method method, T body, IDictionary2 requestParameters) at SharpBucket.SharpBucket.Send[T](T body, Method method, String overrideUrl, IDictionary2 requestParameters) at SharpBucket.V2.EndPoints.RepositoriesEndPoint.GetDiffForPullRequest(String accountName, String repository, Int32 pullRequestId) at SharpBucket.V2.EndPoints.PullRequestResource.GetDiffForPullRequest()
Not sure what's up, but I tried using curl with https://api.bitbucket.org/2.0/repositories/{username}/{repo_slug}/refs/branches/ and I can see that the branches have diffs (some empty, some not). There's some sort of edge case with the data being parsed, although I'm not quite sure what it is specifically.
Currently SharpBucket does not contain any tests, which makes it hard to make changes that affect many different parts. Since the code is mostly just 3rd party api calls it makes no sense to try to do classical unit tests since it would just be mocking everything.
An solution would be to implement integration tests like oktokit.net. Maybe create a repo with dummy data which can then be tested against. And for quite a few of the calls we can just use a public repo with a lot of data.
Any other thoughts?
Hi,
from a service I need to commit some files to our Bitbucket repo but I can't find the Commit method :-
The only one is a PullRequest one but I don't think that I must make a PR for each commit and then approve it :-P
Thanks
valse
I'm struggling to create an issue using the v2 api, is this something that hasn't been implemented yet?
I've created a new repository using the POCO but can't see how it should be posted to the repositories endpoint.
Thanks!
In the last version we added the ability to use SharpBucket with local BitBucket installation. Improve the documentation so that it shows a short example of the use.
The following endpoints currently have activity information, containing updates (and comments?). However, I am missing a separate data type for the approval of a pullrequest (and by whom).
/repositories/{username}/{repo_slug}/pullrequests/activity GET
PullRequestsResource.GetPullRequestLog()
/repositories/{username}/{repo_slug}/pullrequests/{pull_request_id}/activity GET
PullRequestResource.GetPullRequestActivity()
This functionality is listed in the BB documentation, and I have indeed seen it using curl, but I cannot retrieve it within C#.
Am I missing something or could this be added?
I ran into an issue running tests in the SharpBucketTests project. The project targets .NET 4.0, which by default does not enable TLS 1.2. Since Bitbucket has turned off support for TLS 1.0 and 1.1, the tests all fail with an error from RestSharp that a TLS connection could not be established.
The easiest fix would be to change the tests project to target .NET 4.6.2, which does have TLS 1.2 enabled. (SharpBucket itself could continue to target 4.0.)
Another option would be to add a OneTimeSetup
method to SampleRepositories
to explicitly enable current TLS versions, like so:
[OneTimeSetUp]
public void OneTimeSetup()
{
System.Net.ServicePointManager.SecurityProtocol =
(SecurityProtocolType)3072 // TLS 1.2
| (SecurityProtocolType)768 // TLS 1.1
| SecurityProtocolType.Tls;
}
Write a short guide about how other developers can help with contributing (how to setup their machines, what needs fixing, what libraries we are using,...).
Not really an issue more of a question. I don't see any mention in the docs or the test apps about cloning the code in a repo, specifically cloning from a certain tag. Is this possible using this library?
How do I get the last pull request from the master? to avoid the problem I'm having slow. method used: .GetPullRequestLog ()
what is the best way to get all repos for a certain project ?
currently , I only see one option that will get all repos from all projects under the Team account .
The various API calls under /repositories/{username}/{repo_slug}
can take either the repo slug or the UUID as the final part of the path.
The corresponding methods in this library take a string parameter called repository
, which can be either the slug (abc-repo) or the name (ABC Repo). Before building the URL to call, this parameter is run through a method to slugify it -- to make sure that it looks like a slug by replacing spaces and any other illegal chars with hyphens.
This leads to several thoughts:
The parameter is named poorly. It is not clear to a user what a string parameter called repository
can hold.
Users cannot use the UUID to access a repository. BB requires the UUID to be enclosed in { }
, and ParseSlug()
will turn these characters into hyphens when the URL is constructed
It is not clear why the library allows the user to pass in a repo name, which is silently turned into a slug, when the API doesn't allow a repo name to be used.
I suggest that the parameter should be renamed to slugOrUuid
, to make it clear what values the user can pass. The library can also provided a Slugify()
helper function in case the user wants to turn a repo name into a slug, but it shouldn't perform this transformation on its own.
I'm on the fence as to whether the library should attempt to provide any formatting help if the user passes in a UUID. It would be simple to do:
if (Guid.TryParse(slugOrUuid, out var guid))
slugOrUuid = guid.ToString("B");
This would help make sure that the UUID is in the format expected by BB. On the other hand, I can see the argument that this should be the responsibility of the user.
I'm interested in discussion on this topic, and I'm happy to work on a PR if it's decided that some of these changes should be adopted.
I have the description of the Pull Request formatted.
Example: bold, list, table, images.
How can I get this Html for a friendlier presentation?
Should be called PullRequestsResource
, not PullReqestsResource
.
Getting issues only returns 15 of them. I doesn't allow to pass filters either.
namespace SharpBucket.V2.EndPoints
public class RepositoriesEndPoint : EndPoint
{
...
internal Repository PostRepository(Repository repo, string accountName)
{
var overrideUrl = GetRepositoryUrl(accountName, repo.name, null);
return _sharpBucketV2.Post(repo, overrideUrl);
}
...
}
The repo_slug needs to be lowercase, but the Repository.Name can contain uppercase characters
{
"type": "error",
"error": {
"message": "Invalid slug. Slugs must be lowercase, alphanumerical, and may also contain underscores, dashes, or dots."
}
}
I realized belatedly that I probably should have used yield
and returned IEnumerable<T>
instead of List<T>
in PR #10 . By using generators, we only make as many HTTP calls as are required for the user's purpose regardless of whether or not they know max
ahead of time.
I'd like to either refactor the ListX functions to return IEnumerable<X>
or at least add IterateX
functions. I could do this very quickly. The result would be something like this:
public List<Repository> ListRepositories(string accountName, int max = 0){
var overrideUrl = _baseUrl + accountName + "/";
return GetPaginatedValues<Repository>(overrideUrl, max);
}
public IEnumerable<Repository> IterateRepositories (string accountName) {
var overrideUrl = _baseUrl + accountName + "/";
foreach (var val in IteratePaginatedValues<Repository>(overrideUrl )) {
yield return val;
}
}
I don't know that we need both versions, tho. Thoughts. @MitjaBezensek?
I came across this while working on #90 .
Both GetDiff()
and GetPatch()
take an options
parameter which is an object
. Looking at the API here and here I think this parameter should be called spec
and should just be a string; passing in a random object will cause errors.
In addition, GetDiff()
should be able to take an object like ListParameters
that provides context
, path
, ignore_whitespace
, and binary
.
I can put together a PR if you agree that these should be fixed.
The pagination seems to break the OAuth1 authentication. The problem is that the url is just appened to the base url of the resource. For OAuth1 this is problematic since oauth_signature is calculated based on it.
The solution might be quite simple. We should pass a List of parameters to the ExecuteRequest
method which will then just add them as parameters like so: request.AddParameter("pagelen", 30);
I have tested this and it works. @0x1mason are you up for this one since you might be the most familiar with the logic of pagingation?
EndPoint.IteratePages()
assumes that the page
value in a next
link will always be an integer that increments by 1. However, https://developer.atlassian.com/bitbucket/api/2/reference/meta/pagination points out that for some collections, the page
value can be an "unpredictable hash" instead of a sequential number.
I ran into this while retrieving a list of tags.
var tags = tagResource.ListTags("myAccount", "myRepo");
// LIBRARY: GET /2.0/repositories/myAccount/myRepo/refs/tags/?pagelen=50
// BITBUCKET: next=https://api.bitbucket.org/2.0/repositories/myAccount/myRepo/refs/tags/?pagelen=50&page=xGCox
// LIBRARY: GET /2.0/repositories/twengg/abs-core/refs/tags/?pagelen=50&page=2
// BITBUCKET: 404 Not Found
I can put together a PR to pull the page
value directly out of the next
link, instead of just incrementing.
If I do a lot of API requests I may reach the rate limit setupt by bitucket.
In that case BitBucket return an HTTP 429 error response which is not handle at all by SharpBucket and start to an an erratic behavior since it try to interpret the result like if it was an HTTP 200 response.
Exemple of the BitBucket response:
HTTP/1.1 429 Unknown Status Code
Server: nginx
Vary: Authorization
Cache-Control: no-cache, no-store
Content-Type: text/plain
X-OAuth-Scopes: account, team, pullrequest, issue, snippet, webhook
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Date: Fri, 25 Jan 2019 14:55:24 GMT
X-Served-By: app-161
X-Static-Version: 81e1c2138b0b
ETag: "62dcd5481fd29816ecc5ae00be2da0b0"
X-Render-Time: 0.0162138938904
X-Credential-Type: oauth1
X-Accepted-OAuth-Scopes: repository
Connection: Keep-Alive
X-Version: 81e1c2138b0b
X-Request-Count: 447
X-Frame-Options: SAMEORIGIN
Content-Length: 46
Rate limit for this resource has been exceeded
NB: the X-Request-Count
header seems to depends on the X-Served-By
, but it doesn't seems to be of any help for this issue
As you know, the Version1 of Bitbucket Cloud API is deprecated and will be closed on 12 April 2019
https://confluence.atlassian.com/bitbucket/version-1-423626337.html
How should we managed that here ?
When should we start to drop the SharpBucketV1 class and all the code that is behind ?
If I look at the current state of the developement of SharpBucket:
Release 0.7.2 Is the last one to have improved API V1 implementation (released in march)
Release 0.7.3 and all code already in master or in progress concern only API V2 implementation
So we can reasonably though that we won't maintain any more the API V1 implementation since nobody has shown any interest for that since months
In that context I suggest to tag the SharpBucketV1 class as obsolete for a next release. That release (0.8.0 if we are agree quickly ?) can be used by consumers to detect where they have code to change
Then in a next release (0.9.0 ?) we remove the class and all the code that is linked to API V1
Consumers that want to stay on the API V1 until the final date can stay on Release 0.7.3 (or on 0.8.0 with warnings), they are not forced to upgrade. So it should not stop us to stop supporting the API V1 before the final date.
Furthermore, at the final date our unit tests will break if we haven't drop the code before, which means that it would be better to drop that code not too late.
@MitjaBezensek, @asherber, are you agree with that strategy ?
We have multiple classes and methods which name is not obvious to distinct OAuth1 vs OAuth2
In particular the following classes:
OAuthentication2Legged
and OAuthentication3Legged
which are OAuth1OAuthentication2
which is OAuth2And the corresponding methods in SharpBucket
class:
OAuth2LeggedAuthentication
and OAuth3LeggedAuthentication
which are OAuth1OAuthentication2
which is OAuth2The issue comes from the fact that "OAuth 2 legged" is clearly not "Oauth2 legged", but when all is join in a method name its become hard to distinct both.
Can we try to deprecate that methods and classes for methods with more explicit naming ?
My suggestion would be to harmonize the classes and methods names to be the same, and named like that:
OAuth2LeggedAuthentication
=> OAuthWith2LeggedAuthentication
OAuth3LeggedAuthentication
=> OAuthWith3LeggedAuthentication
OAuthentication2
=> OAuth2WithClientCredentialsGrant
(because it's named like that here : https://developer.atlassian.com/bitbucket/api/2/reference/meta/authentication, and it will let us the door open to implements others OAuth2 scenarios like the "Resource Owner Password Credentials Grant" which is probably an improvement of the BasicAuthentication
that we already have)
Hello, I would like to know if this endpoint is already covered OR if there's a way to do a custom endpoint call using this lib.
More specifically this endpoint which is not listed on Coverage.md
REST client encountered an error: Value was either too large or too small for a UInt64.
Cannot debug this. Has htis been encountered before?
Currently the RepositoriesEndPoint's ListRepositories method does not allow retrieving more than first 10 results - I would like to be able to retrieve more than that.
Currently the wrapper can't be used for on-prem hosted Bitbucket solutions. Customizing the base URL would fix that.
When I call SrcResource.GetFileContent(string) for a file that do not exists, I do not expect to get in return the JSON error response of BitBucket
A better error handling is needed !
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.