diff --git a/BuildaGitServer/BitBucket/BitBucketComment.swift b/BuildaGitServer/BitBucket/BitBucketComment.swift new file mode 100644 index 0000000..2a9e439 --- /dev/null +++ b/BuildaGitServer/BitBucket/BitBucketComment.swift @@ -0,0 +1,25 @@ +// +// BitBucketComment.swift +// Buildasaur +// +// Created by Honza Dvorsky on 1/27/16. +// Copyright © 2016 Honza Dvorsky. All rights reserved. +// + +import Foundation + +class BitBucketComment: BitBucketEntity, CommentType { + + let body: String + + required init(json: NSDictionary) { + + self.body = json + .dictionaryForKey("content") + .stringForKey("raw") + + super.init(json: json) + } + + +} diff --git a/BuildaGitServer/BitBucket/BitBucketEndpoints.swift b/BuildaGitServer/BitBucket/BitBucketEndpoints.swift index 6e08b0a..f8386b2 100644 --- a/BuildaGitServer/BitBucket/BitBucketEndpoints.swift +++ b/BuildaGitServer/BitBucket/BitBucketEndpoints.swift @@ -14,6 +14,8 @@ class BitBucketEndpoints { enum Endpoint { case Repos case PullRequests + case PullRequestComments + case CommitStatuses } private let baseURL: String @@ -46,8 +48,31 @@ class BitBucketEndpoints { } else { return "\(repo)/pullrequests" } - + + case .PullRequestComments: + + assert(params?["repo"] != nil, "A repo must be specified") + assert(params?["pr"] != nil, "A PR must be specified") + let pr = self.endpointURL(.PullRequests, params: params) + return "\(pr)/comments" + + case .CommitStatuses: + + assert(params?["repo"] != nil, "A repo must be specified") + assert(params?["sha"] != nil, "A commit sha must be specified") + let repo = self.endpointURL(.Repos, params: params) + let sha = params!["sha"]! + + let build = "\(repo)/commit/\(sha)/statuses/build" + + if let key = params?["status_key"] { + return "\(build)/\(key)" + } + + return build + } + } func createRequest(method: HTTP.Method, endpoint: Endpoint, params: [String : String]? = nil, query: [String : String]? = nil, body: NSDictionary? = nil) throws -> NSMutableURLRequest { @@ -64,8 +89,12 @@ class BitBucketEndpoints { if let auth = self.auth { switch auth.type { - case .PersonalToken, .OAuthToken: - request.setValue("token \(auth.secret)", forHTTPHeaderField:"Authorization") + case .OAuthToken: + let tokens = auth.secret.componentsSeparatedByString(":") + //first is refresh token, second access token + request.setValue("Bearer \(tokens[1])", forHTTPHeaderField:"Authorization") + default: + fatalError("This kind of authentication is not supported for BitBucket") } } @@ -73,6 +102,7 @@ class BitBucketEndpoints { let data = try NSJSONSerialization.dataWithJSONObject(body, options: NSJSONWritingOptions()) request.HTTPBody = data + request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") } return request diff --git a/BuildaGitServer/BitBucket/BitBucketServer.swift b/BuildaGitServer/BitBucket/BitBucketServer.swift index 18ec6e2..474c019 100644 --- a/BuildaGitServer/BitBucket/BitBucketServer.swift +++ b/BuildaGitServer/BitBucket/BitBucketServer.swift @@ -26,12 +26,16 @@ extension BitBucketServer: SourceServerType { func createStatusFromState(state: BuildState, description: String?, targetUrl: String?) -> StatusType { - //TODO: replace with bitbucket types - return GitHubStatus(state: GitHubStatus.GitHubState.NoState, description: nil, targetUrl: nil, context: nil) + let bbState = BitBucketStatus.BitBucketState.fromBuildState(state) + let key = "Buildasaur" + let url = targetUrl ?? "https://github.com/czechboy0/Buildasaur" + return BitBucketStatus(state: bbState, key: key, name: key, description: description, url: url) } func getBranchesOfRepo(repo: String, completion: (branches: [BranchType]?, error: ErrorType?) -> ()) { + //TODO: start returning branches + completion(branches: [], error: nil) } func getOpenPullRequests(repo: String, completion: (prs: [PullRequestType]?, error: ErrorType?) -> ()) { @@ -57,26 +61,131 @@ extension BitBucketServer: SourceServerType { func getPullRequest(pullRequestNumber: Int, repo: String, completion: (pr: PullRequestType?, error: ErrorType?) -> ()) { + let params = [ + "repo": repo, + "pr": pullRequestNumber.description + ] + + self._sendRequestWithMethod(.GET, endpoint: .PullRequests, params: params, query: nil, body: nil) { (response, body, error) -> () in + + if error != nil { + completion(pr: nil, error: error) + return + } + + if let body = body as? NSDictionary { + let pr = BitBucketPullRequest(json: body) + completion(pr: pr, error: nil) + } else { + completion(pr: nil, error: Error.withInfo("Wrong body \(body)")) + } + } } func getRepo(repo: String, completion: (repo: RepoType?, error: ErrorType?) -> ()) { + let params = [ + "repo": repo + ] + + self._sendRequestWithMethod(.GET, endpoint: .Repos, params: params, query: nil, body: nil) { + (response, body, error) -> () in + + if error != nil { + completion(repo: nil, error: error) + return + } + + if let body = body as? NSDictionary { + let repository = BitBucketRepo(json: body) + completion(repo: repository, error: nil) + } else { + completion(repo: nil, error: Error.withInfo("Wrong body \(body)")) + } + } } func getStatusOfCommit(commit: String, repo: String, completion: (status: StatusType?, error: ErrorType?) -> ()) { + let params = [ + "repo": repo, + "sha": commit, + "status_key": "Buildasaur" + ] + + self._sendRequestWithMethod(.GET, endpoint: .CommitStatuses, params: params, query: nil, body: nil) { (response, body, error) -> () in + + if response?.statusCode == 404 { + //no status yet, just pass nil but OK + completion(status: nil, error: nil) + return + } + + if error != nil { + completion(status: nil, error: error) + return + } + + if let body = body as? NSDictionary { + let status = BitBucketStatus(json: body) + completion(status: status, error: nil) + } else { + completion(status: nil, error: Error.withInfo("Wrong body \(body)")) + } + } } func postStatusOfCommit(commit: String, status: StatusType, repo: String, completion: (status: StatusType?, error: ErrorType?) -> ()) { + let params = [ + "repo": repo, + "sha": commit + ] + + let body = (status as! BitBucketStatus).dictionarify() + self._sendRequestWithMethod(.POST, endpoint: .CommitStatuses, params: params, query: nil, body: body) { (response, body, error) -> () in + + if error != nil { + completion(status: nil, error: error) + return + } + + if let body = body as? NSDictionary { + let status = BitBucketStatus(json: body) + completion(status: status, error: nil) + } else { + completion(status: nil, error: Error.withInfo("Wrong body \(body)")) + } + } } func postCommentOnIssue(comment: String, issueNumber: Int, repo: String, completion: (comment: CommentType?, error: ErrorType?) -> ()) { + //TODO + completion(comment: nil, error: Error.withInfo("Posting comments on BitBucket not yet supported")) } func getCommentsOfIssue(issueNumber: Int, repo: String, completion: (comments: [CommentType]?, error: ErrorType?) -> ()) { + let params = [ + "repo": repo, + "pr": issueNumber.description + ] + + self._sendRequestWithMethod(.GET, endpoint: .PullRequestComments, params: params, query: nil, body: nil) { (response, body, error) -> () in + + if error != nil { + completion(comments: nil, error: error) + return + } + + if let body = body as? NSDictionary { + let comments: [BitBucketComment] = BitBucketArray(body) + completion(comments: comments.map { $0 as CommentType }, error: nil) + } else { + completion(comments: nil, error: Error.withInfo("Wrong body \(body)")) + } + } } } diff --git a/BuildaGitServer/BitBucket/BitBucketStatus.swift b/BuildaGitServer/BitBucket/BitBucketStatus.swift new file mode 100644 index 0000000..9807080 --- /dev/null +++ b/BuildaGitServer/BitBucket/BitBucketStatus.swift @@ -0,0 +1,82 @@ +// +// BitBucketStatus.swift +// Buildasaur +// +// Created by Honza Dvorsky on 1/27/16. +// Copyright © 2016 Honza Dvorsky. All rights reserved. +// + +import Foundation + +class BitBucketStatus: BitBucketEntity, StatusType { + + enum BitBucketState: String { + case InProgress = "INPROGRESS" + case Success = "SUCCESSFUL" + case Failed = "FAILED" + } + + let bbState: BitBucketState + let key: String + let name: String? + let description: String? + let targetUrl: String? + + required init(json: NSDictionary) { + + self.bbState = BitBucketState(rawValue: json.stringForKey("state"))! + self.key = json.stringForKey("key") + self.name = json.optionalStringForKey("name") + self.description = json.optionalStringForKey("description") + self.targetUrl = json.stringForKey("url") + + super.init(json: json) + } + + init(state: BitBucketState, key: String, name: String?, description: String?, url: String) { + + self.bbState = state + self.key = key + self.name = name + self.description = description + self.targetUrl = url + + super.init() + } + + var state: BuildState { + return self.bbState.toBuildState() + } + + override func dictionarify() -> NSDictionary { + + let dictionary = NSMutableDictionary() + + dictionary["state"] = self.bbState.rawValue + dictionary["key"] = self.key + dictionary.optionallyAddValueForKey(self.description, key: "description") + dictionary.optionallyAddValueForKey(self.name, key: "name") + dictionary.optionallyAddValueForKey(self.targetUrl, key: "url") + + return dictionary.copy() as! NSDictionary + } +} + +extension BitBucketStatus.BitBucketState { + + static func fromBuildState(state: BuildState) -> BitBucketStatus.BitBucketState { + switch state { + case .Success, .NoState: return .Success + case .Pending: return .InProgress + case .Error, .Failure: return .Failed + } + } + + func toBuildState() -> BuildState { + switch self { + case .Success: return .Success + case .InProgress: return .Pending + case .Failed: return .Failure + } + } +} diff --git a/BuildaGitServer/GitHub/GitHubStatus.swift b/BuildaGitServer/GitHub/GitHubStatus.swift index c9acf8c..2cc4654 100644 --- a/BuildaGitServer/GitHub/GitHubStatus.swift +++ b/BuildaGitServer/GitHub/GitHubStatus.swift @@ -97,19 +97,6 @@ class GitHubStatus : GitHubEntity { } } -//for sending statuses upstream -extension GitHubStatus { - - class func toDict(state: GitHubState, description: String? = nil, targetUrl: String? = nil, context: String? = nil) -> [String: String] { - return [ - "state" : state.rawValue, - "target_url" : targetUrl ?? "", - "description" : description ?? "", - "context" : context ?? "" - ] - } -} - extension GitHubStatus: StatusType { var state: BuildState { diff --git a/BuildaGitServerTests/BitBucketServerTests.swift b/BuildaGitServerTests/BitBucketServerTests.swift index 7a57781..71391be 100644 --- a/BuildaGitServerTests/BitBucketServerTests.swift +++ b/BuildaGitServerTests/BitBucketServerTests.swift @@ -63,4 +63,122 @@ class BitBucketServerTests: XCTestCase { self.waitForExpectationsWithTimeout(10, handler: nil) } + func testGetPullRequest() { + + self.prepServerWithName("bitbucket_get_pr") + + let exp = self.expectationWithDescription("Waiting for url request") + + self.bitbucket.getPullRequest(4, repo: "honzadvorsky/buildasaur-tester") { (pr, error) -> () in + + expect(error).to(beNil()) + guard let pr = pr else { fail(); return } + + expect(pr.title) == "README.md edited online with Bitbucket" + expect(pr.number) == 4 + expect(pr.baseName) == "czechboy0-patch-6" + expect(pr.headCommitSHA) == "787ce956a784" + expect(pr.headName) == "honzadvorsky/readmemd-edited-online-with-bitbucket-1453476305123" + expect(pr.headRepo.originUrlSSH) == "git@bitbucket.org:honzadvorsky/buildasaur-tester.git" + + exp.fulfill() + } + + self.waitForExpectationsWithTimeout(10, handler: nil) + } + + func testGetRepo() { + + self.prepServerWithName("bitbucket_get_repo") + + let exp = self.expectationWithDescription("Waiting for url request") + + self.bitbucket.getRepo("honzadvorsky/buildasaur-tester") { (repo, error) -> () in + + expect(error).to(beNil()) + guard let repo = repo else { fail(); return } + + expect(repo.originUrlSSH) == "git@bitbucket.org:honzadvorsky/buildasaur-tester.git" + + exp.fulfill() + } + + self.waitForExpectationsWithTimeout(10, handler: nil) + } + + func testGetComments() { + + self.prepServerWithName("bitbucket_get_comments") + + let exp = self.expectationWithDescription("Waiting for url request") + + self.bitbucket.getCommentsOfIssue(4, repo: "honzadvorsky/buildasaur-tester") { (comments, error) -> () in + + expect(error).to(beNil()) + guard let comments: [CommentType] = comments else { fail(); return } + + expect(comments.count) == 2 + let c1 = comments[0].body + let c2 = comments[1].body + expect(c1) == "Another **hello world**" + expect(c2) == "Hello world" + + exp.fulfill() + } + + self.waitForExpectationsWithTimeout(10, handler: nil) + } + + func testPostStatus() { + + self.prepServerWithName("bitbucket_post_status") + + let exp = self.expectationWithDescription("Waiting for url request") + + let status = self.bitbucket.createStatusFromState(BuildState.Success, description: "All went great!", targetUrl: "https://stlt.herokuapp.com/v1/xcs_deeplink/honzadvysmbpr14.home/1413f8578e54c3d052b8121a250255c0/1413f8578e54c3d052b8121a2509a923") + + self.bitbucket.postStatusOfCommit("787ce95", status: status, repo: "honzadvorsky/buildasaur-tester") { (status, error) -> () in + + expect(error).to(beNil()) + guard let status = status else { fail(); return } + + expect(status.description) == "All went great!" + expect(status.state) == BuildState.Success + expect(status.targetUrl) == "https://stlt.herokuapp.com/v1/xcs_deeplink/honzadvysmbpr14.home/1413f8578e54c3d052b8121a250255c0/1413f8578e54c3d052b8121a2509a923" + + exp.fulfill() + } + + self.waitForExpectationsWithTimeout(10, handler: nil) + } + + func testGetStatus() { + + self.prepServerWithName("bitbucket_get_status") + + let exp = self.expectationWithDescription("Waiting for url request") + + self.bitbucket.getStatusOfCommit("787ce95", repo: "honzadvorsky/buildasaur-tester") { (status, error) -> () in + + expect(error).to(beNil()) + guard let status = status else { fail(); return } + + expect(status.description) == "All went great!" + expect(status.state) == BuildState.Success + expect(status.targetUrl) == "https://stlt.herokuapp.com/v1/xcs_deeplink/honzadvysmbpr14.home/1413f8578e54c3d052b8121a250255c0/1413f8578e54c3d052b8121a2509a923" + + exp.fulfill() + } + + self.waitForExpectationsWithTimeout(10, handler: nil) + } + + // func testPostComment() { + // //TODO: + // } + + // func testGetBranches() { + // //TODO: + // } + } diff --git a/BuildaGitServerTests/Data/bitbucket_get_comments.json b/BuildaGitServerTests/Data/bitbucket_get_comments.json new file mode 100644 index 0000000..6c2e091 --- /dev/null +++ b/BuildaGitServerTests/Data/bitbucket_get_comments.json @@ -0,0 +1,142 @@ +{ + "interactions" : [ + { + "recorded_at" : 1453928110.383976, + "response" : { + "body" : { + "page" : 1, + "size" : 2, + "pagelen" : 10, + "values" : [ + { + "content" : { + "raw" : "Another **hello world**", + "markup" : "markdown", + "html" : "
Another hello world<\/strong><\/p>"
+ },
+ "updated_on" : "2016-01-27T20:47:11.950649+00:00",
+ "id" : 13923541,
+ "pullrequest" : {
+ "id" : 4,
+ "links" : {
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/pull-requests\/4"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4"
+ }
+ },
+ "title" : "README.md edited online with Bitbucket",
+ "type" : "pullrequest"
+ },
+ "links" : {
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/pull-requests\/4\/_\/diff#comment-13923541"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/comments\/13923541"
+ }
+ },
+ "created_on" : "2016-01-27T20:46:56.523167+00:00",
+ "user" : {
+ "username" : "honzadvorsky",
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/account\/honzadvorsky\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/users\/honzadvorsky"
+ }
+ },
+ "display_name" : "Honza Dvorsky",
+ "type" : "user",
+ "uuid" : "{c78fc04e-2594-4f79-a518-ae1593921663}"
+ }
+ },
+ {
+ "content" : {
+ "raw" : "Hello world",
+ "markup" : "markdown",
+ "html" : " Hello world<\/p>"
+ },
+ "updated_on" : "2016-01-27T20:46:17.899168+00:00",
+ "id" : 13923520,
+ "pullrequest" : {
+ "id" : 4,
+ "links" : {
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/pull-requests\/4"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4"
+ }
+ },
+ "title" : "README.md edited online with Bitbucket",
+ "type" : "pullrequest"
+ },
+ "links" : {
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/pull-requests\/4\/_\/diff#comment-13923520"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/comments\/13923520"
+ }
+ },
+ "created_on" : "2016-01-27T20:46:17.897343+00:00",
+ "user" : {
+ "username" : "honzadvorsky",
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/account\/honzadvorsky\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/users\/honzadvorsky"
+ }
+ },
+ "display_name" : "Honza Dvorsky",
+ "type" : "user",
+ "uuid" : "{c78fc04e-2594-4f79-a518-ae1593921663}"
+ }
+ }
+ ]
+ },
+ "status" : 200,
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/comments",
+ "headers" : {
+ "Content-Type" : "application\/json; charset=utf-8",
+ "X-Render-Time" : "0.0898499488831",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "X-Cache-Info" : "caching",
+ "Content-Encoding" : "gzip",
+ "Server" : "nginx\/1.6.2",
+ "X-Accepted-OAuth-Scopes" : "pullrequest",
+ "Transfer-Encoding" : "Identity",
+ "X-Request-Count" : "161",
+ "X-Version" : "66b40159990c",
+ "Cache-Control" : "max-age=900",
+ "Date" : "Wed, 27 Jan 2016 20:55:10 GMT",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Static-Version" : "66b40159990c",
+ "Connection" : "keep-alive",
+ "X-Content-Type-Options" : "nosniff",
+ "X-Served-By" : "app19",
+ "Vary" : "Authorization, Cookie, Accept-Encoding"
+ }
+ },
+ "request" : {
+ "method" : "GET",
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/comments",
+ "headers" : {
+
+ }
+ }
+ }
+ ],
+ "name" : "bitbucket_get_comments"
+}
diff --git a/BuildaGitServerTests/Data/bitbucket_get_pr.json b/BuildaGitServerTests/Data/bitbucket_get_pr.json
new file mode 100644
index 0000000..6d305f7
--- /dev/null
+++ b/BuildaGitServerTests/Data/bitbucket_get_pr.json
@@ -0,0 +1,166 @@
+{
+ "interactions" : [
+ {
+ "recorded_at" : 1453927044.153671,
+ "response" : {
+ "body" : {
+ "description" : "README.md edited online with Bitbucket",
+ "state" : "OPEN",
+ "comment_count" : 0,
+ "id" : 4,
+ "reviewers" : [
+
+ ],
+ "author" : {
+ "username" : "honzadvorsky",
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/account\/honzadvorsky\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/users\/honzadvorsky"
+ }
+ },
+ "display_name" : "Honza Dvorsky",
+ "type" : "user",
+ "uuid" : "{c78fc04e-2594-4f79-a518-ae1593921663}"
+ },
+ "merge_commit" : null,
+ "close_source_branch" : true,
+ "closed_by" : null,
+ "source" : {
+ "branch" : {
+ "name" : "honzadvorsky\/readmemd-edited-online-with-bitbucket-1453476305123"
+ },
+ "commit" : {
+ "hash" : "787ce956a784",
+ "links" : {
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce956a784"
+ }
+ }
+ },
+ "repository" : {
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester"
+ }
+ },
+ "full_name" : "honzadvorsky\/buildasaur-tester",
+ "type" : "repository",
+ "name" : "Buildasaur-Tester",
+ "uuid" : "{c839d4b0-eeb6-4e09-865e-f29db3e51f28}"
+ }
+ },
+ "title" : "README.md edited online with Bitbucket",
+ "created_on" : "2016-01-22T15:25:09.703811+00:00",
+ "participants" : [
+
+ ],
+ "type" : "pullrequest",
+ "links" : {
+ "comments" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/comments"
+ },
+ "decline" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/decline"
+ },
+ "commits" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/commits"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/pull-requests\/4"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4"
+ },
+ "merge" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/merge"
+ },
+ "activity" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/activity"
+ },
+ "diff" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/diff"
+ },
+ "approve" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4\/approve"
+ }
+ },
+ "reason" : "",
+ "destination" : {
+ "branch" : {
+ "name" : "czechboy0-patch-6"
+ },
+ "commit" : {
+ "hash" : "eeac335d8077",
+ "links" : {
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/eeac335d8077"
+ }
+ }
+ },
+ "repository" : {
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester"
+ }
+ },
+ "full_name" : "honzadvorsky\/buildasaur-tester",
+ "type" : "repository",
+ "name" : "Buildasaur-Tester",
+ "uuid" : "{c839d4b0-eeb6-4e09-865e-f29db3e51f28}"
+ }
+ },
+ "task_count" : 0,
+ "updated_on" : "2016-01-22T15:29:04.285575+00:00"
+ },
+ "status" : 200,
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4",
+ "headers" : {
+ "Content-Type" : "application\/json; charset=utf-8",
+ "X-Render-Time" : "0.0324521064758",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "X-Cache-Info" : "caching",
+ "Content-Encoding" : "gzip",
+ "Server" : "nginx\/1.6.2",
+ "X-Accepted-OAuth-Scopes" : "pullrequest",
+ "Transfer-Encoding" : "Identity",
+ "X-Request-Count" : "471",
+ "X-Version" : "66b40159990c",
+ "Cache-Control" : "max-age=900",
+ "Date" : "Wed, 27 Jan 2016 20:37:24 GMT",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Static-Version" : "66b40159990c",
+ "Connection" : "keep-alive",
+ "X-Content-Type-Options" : "nosniff",
+ "X-Served-By" : "app22",
+ "Vary" : "Authorization, Cookie, Accept-Encoding"
+ }
+ },
+ "request" : {
+ "method" : "GET",
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests\/4",
+ "headers" : {
+
+ }
+ }
+ }
+ ],
+ "name" : "bitbucket_get_pr"
+}
diff --git a/BuildaGitServerTests/Data/bitbucket_get_repo.json b/BuildaGitServerTests/Data/bitbucket_get_repo.json
new file mode 100644
index 0000000..fedff78
--- /dev/null
+++ b/BuildaGitServerTests/Data/bitbucket_get_repo.json
@@ -0,0 +1,112 @@
+{
+ "interactions" : [
+ {
+ "recorded_at" : 1453927330.056467,
+ "response" : {
+ "body" : {
+ "uuid" : "{c839d4b0-eeb6-4e09-865e-f29db3e51f28}",
+ "full_name" : "honzadvorsky\/buildasaur-tester",
+ "description" : "",
+ "owner" : {
+ "username" : "honzadvorsky",
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/account\/honzadvorsky\/avatar\/32\/"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/users\/honzadvorsky"
+ }
+ },
+ "display_name" : "Honza Dvorsky",
+ "type" : "user",
+ "uuid" : "{c78fc04e-2594-4f79-a518-ae1593921663}"
+ },
+ "type" : "repository",
+ "size" : 163544,
+ "created_on" : "2016-01-21T19:29:27.826816+00:00",
+ "has_wiki" : false,
+ "fork_policy" : "allow_forks",
+ "links" : {
+ "avatar" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester\/avatar\/32\/"
+ },
+ "forks" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/forks"
+ },
+ "pullrequests" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/pullrequests"
+ },
+ "html" : {
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester"
+ },
+ "commits" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commits"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester"
+ },
+ "hooks" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/hooks"
+ },
+ "downloads" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/downloads"
+ },
+ "clone" : [
+ {
+ "name" : "https",
+ "href" : "https:\/\/bitbucket.org\/honzadvorsky\/buildasaur-tester.git"
+ },
+ {
+ "name" : "ssh",
+ "href" : "ssh:\/\/git@bitbucket.org\/honzadvorsky\/buildasaur-tester.git"
+ }
+ ],
+ "watchers" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/watchers"
+ }
+ },
+ "language" : "swift",
+ "scm" : "git",
+ "has_issues" : false,
+ "website" : "",
+ "is_private" : false,
+ "name" : "Buildasaur-Tester",
+ "updated_on" : "2016-01-27T17:08:54.773844+00:00"
+ },
+ "status" : 200,
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester",
+ "headers" : {
+ "Content-Type" : "application\/json; charset=utf-8",
+ "X-Render-Time" : "0.0204379558563",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "X-Cache-Info" : "caching",
+ "Content-Encoding" : "gzip",
+ "Server" : "nginx\/1.6.2",
+ "X-Accepted-OAuth-Scopes" : "repository",
+ "Transfer-Encoding" : "Identity",
+ "X-Request-Count" : "471",
+ "X-Version" : "66b40159990c",
+ "Cache-Control" : "max-age=900",
+ "Date" : "Wed, 27 Jan 2016 20:42:09 GMT",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Static-Version" : "66b40159990c",
+ "Connection" : "keep-alive",
+ "X-Content-Type-Options" : "nosniff",
+ "X-Served-By" : "app22",
+ "Vary" : "Authorization, Cookie, Accept-Encoding"
+ }
+ },
+ "request" : {
+ "method" : "GET",
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester",
+ "headers" : {
+
+ }
+ }
+ }
+ ],
+ "name" : "bitbucket_get_repo"
+}
diff --git a/BuildaGitServerTests/Data/bitbucket_get_status.json b/BuildaGitServerTests/Data/bitbucket_get_status.json
new file mode 100644
index 0000000..0ad8c10
--- /dev/null
+++ b/BuildaGitServerTests/Data/bitbucket_get_status.json
@@ -0,0 +1,56 @@
+{
+ "interactions" : [
+ {
+ "recorded_at" : 1453932419.386528,
+ "response" : {
+ "body" : {
+ "state" : "SUCCESSFUL",
+ "updated_on" : "2016-01-27T22:00:48.330475+00:00",
+ "description" : "All went great!",
+ "links" : {
+ "commit" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce956a784346755ac1a01da7bc1e20f87c006"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce956a784346755ac1a01da7bc1e20f87c006\/statuses\/build\/Buildasaur"
+ }
+ },
+ "key" : "Buildasaur",
+ "created_on" : "2016-01-27T21:52:34.066284+00:00",
+ "type" : "build",
+ "name" : "Buildasaur",
+ "url" : "https:\/\/stlt.herokuapp.com\/v1\/xcs_deeplink\/honzadvysmbpr14.home\/1413f8578e54c3d052b8121a250255c0\/1413f8578e54c3d052b8121a2509a923"
+ },
+ "status" : 200,
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce95\/statuses\/build\/Buildasaur",
+ "headers" : {
+ "Content-Type" : "application\/json; charset=utf-8",
+ "X-Render-Time" : "0.498512983322",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "Content-Encoding" : "gzip",
+ "Server" : "nginx\/1.6.2",
+ "X-Accepted-OAuth-Scopes" : "repository",
+ "Transfer-Encoding" : "Identity",
+ "X-Request-Count" : "69",
+ "X-OAuth-Scopes" : "pullrequest:write",
+ "X-Version" : "66b40159990c",
+ "Date" : "Wed, 27 Jan 2016 22:06:59 GMT",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Static-Version" : "66b40159990c",
+ "Connection" : "keep-alive",
+ "X-Content-Type-Options" : "nosniff",
+ "X-Served-By" : "app18",
+ "Vary" : "Authorization, Cookie"
+ }
+ },
+ "request" : {
+ "method" : "GET",
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce95\/statuses\/build\/Buildasaur",
+ "headers" : {
+ "Authorization" : "Bearer dont_looky_here"
+ }
+ }
+ }
+ ],
+ "name" : "bitbucket_get_status"
+}
diff --git a/BuildaGitServerTests/Data/bitbucket_post_status.json b/BuildaGitServerTests/Data/bitbucket_post_status.json
new file mode 100644
index 0000000..ba82498
--- /dev/null
+++ b/BuildaGitServerTests/Data/bitbucket_post_status.json
@@ -0,0 +1,64 @@
+{
+ "interactions" : [
+ {
+ "recorded_at" : 1453932048.4355,
+ "response" : {
+ "body" : {
+ "state" : "SUCCESSFUL",
+ "updated_on" : "2016-01-27T22:00:48.330475+00:00",
+ "description" : "All went great!",
+ "links" : {
+ "commit" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce956a784346755ac1a01da7bc1e20f87c006"
+ },
+ "self" : {
+ "href" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce956a784346755ac1a01da7bc1e20f87c006\/statuses\/build\/Buildasaur"
+ }
+ },
+ "key" : "Buildasaur",
+ "created_on" : "2016-01-27T21:52:34.066284+00:00",
+ "type" : "build",
+ "name" : "Buildasaur",
+ "url" : "https:\/\/stlt.herokuapp.com\/v1\/xcs_deeplink\/honzadvysmbpr14.home\/1413f8578e54c3d052b8121a250255c0\/1413f8578e54c3d052b8121a2509a923"
+ },
+ "status" : 200,
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce95\/statuses\/build",
+ "headers" : {
+ "Content-Type" : "application\/json",
+ "X-Render-Time" : "0.0719389915466",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "Content-Encoding" : "gzip",
+ "Server" : "nginx\/1.6.2",
+ "X-Accepted-OAuth-Scopes" : "repository",
+ "Transfer-Encoding" : "Identity",
+ "X-Request-Count" : "494",
+ "X-OAuth-Scopes" : "pullrequest:write",
+ "X-Version" : "66b40159990c",
+ "Date" : "Wed, 27 Jan 2016 22:00:48 GMT",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Static-Version" : "66b40159990c",
+ "Connection" : "keep-alive",
+ "X-Content-Type-Options" : "nosniff",
+ "X-Served-By" : "app19",
+ "Vary" : "Authorization, Cookie"
+ }
+ },
+ "request" : {
+ "method" : "POST",
+ "body" : {
+ "state" : "SUCCESSFUL",
+ "key" : "Buildasaur",
+ "description" : "All went great!",
+ "name" : "Buildasaur",
+ "url" : "https:\/\/stlt.herokuapp.com\/v1\/xcs_deeplink\/honzadvysmbpr14.home\/1413f8578e54c3d052b8121a250255c0\/1413f8578e54c3d052b8121a2509a923"
+ },
+ "url" : "https:\/\/api.bitbucket.org\/2.0\/repositories\/honzadvorsky\/buildasaur-tester\/commit\/787ce95\/statuses\/build",
+ "headers" : {
+ "Authorization" : "Bearer abcd_dont_loook_here",
+ "Content-Type" : "application\/json; charset=utf-8"
+ }
+ }
+ }
+ ],
+ "name" : "bitbucket_post_status"
+}
diff --git a/BuildaKit/SyncPairResolver.swift b/BuildaKit/SyncPairResolver.swift
index 8769b88..8881793 100644
--- a/BuildaKit/SyncPairResolver.swift
+++ b/BuildaKit/SyncPairResolver.swift
@@ -148,7 +148,7 @@ public class SyncPairResolver {
//if it's not pending, we need to take a look at the blueprint and inspect the SHA.
if let blueprint = integration.blueprint, let sha = blueprint.commitSHA {
- return sha == headCommit
+ return sha.hasPrefix(headCommit) //headCommit is sometimes a short version only
}
//when an integration is Pending, Preparing or Checking out, it doesn't have a blueprint, but it is, by definition, a headCommit
diff --git a/Buildasaur.xcodeproj/project.pbxproj b/Buildasaur.xcodeproj/project.pbxproj
index add0530..3af0b82 100644
--- a/Buildasaur.xcodeproj/project.pbxproj
+++ b/Buildasaur.xcodeproj/project.pbxproj
@@ -10,6 +10,8 @@
079FD08F18890B9ED0EEC9A5 /* Pods_BuildaKitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB2056DC704255FB4A676BA5 /* Pods_BuildaKitTests.framework */; };
0E33784B1AC8F17E34DEEB74 /* Pods_Buildasaur.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E259E9106C895130138567A /* Pods_Buildasaur.framework */; };
15A92AB3A2DE8DA7A566FB3F /* Pods_BuildaGitServerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16B84F653EF9BEA46717FE32 /* Pods_BuildaGitServerTests.framework */; };
+ 3A0034F01C5975C000A4ECB5 /* bitbucket_post_status.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A0034EF1C5975C000A4ECB5 /* bitbucket_post_status.json */; };
+ 3A0034F21C59775100A4ECB5 /* bitbucket_get_status.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A0034F11C59775100A4ECB5 /* bitbucket_get_status.json */; };
3A014BA51C57A94B00B82B4A /* Authentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A014BA41C57A94B00B82B4A /* Authentication.swift */; };
3A08B3611C58301D00ED7A1F /* github.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A08B3601C58301D00ED7A1F /* github.png */; };
3A08B3641C5837EA00ED7A1F /* ServiceAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A08B3631C5837EA00ED7A1F /* ServiceAuthentication.swift */; };
@@ -45,6 +47,11 @@
3A756DCC1BAB44A200508B69 /* BuildaHeartbeatKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A756DBD1BAB425E00508B69 /* BuildaHeartbeatKit.framework */; };
3A7577AB1C593A740023F08C /* bitbucket_get_prs.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A7577AA1C593A740023F08C /* bitbucket_get_prs.json */; };
3A7577AD1C593C5C0023F08C /* BitBucketPullRequestBranch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7577AC1C593C5C0023F08C /* BitBucketPullRequestBranch.swift */; };
+ 3A7577AF1C59621E0023F08C /* bitbucket_get_pr.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A7577AE1C59621E0023F08C /* bitbucket_get_pr.json */; };
+ 3A7577B11C5963440023F08C /* bitbucket_get_repo.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A7577B01C5963440023F08C /* bitbucket_get_repo.json */; };
+ 3A7577B31C5963BF0023F08C /* BitBucketComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7577B21C5963BF0023F08C /* BitBucketComment.swift */; };
+ 3A7577B51C5966530023F08C /* bitbucket_get_comments.json in Resources */ = {isa = PBXBuildFile; fileRef = 3A7577B41C5966530023F08C /* bitbucket_get_comments.json */; };
+ 3A7577B71C59691A0023F08C /* BitBucketStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7577B61C59691A0023F08C /* BitBucketStatus.swift */; };
3A7AF60E1C590CC4000FD726 /* bitbucket.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A7AF60D1C590CC4000FD726 /* bitbucket.png */; };
3A7AF6101C591FAD000FD726 /* BitBucketServerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7AF60F1C591FAD000FD726 /* BitBucketServerTests.swift */; };
3A7AF6121C592023000FD726 /* BitBucketServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7AF6111C592023000FD726 /* BitBucketServer.swift */; };
@@ -239,6 +246,8 @@
17FE44590CED1491A8F03F35 /* Pods-BuildaKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildaKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BuildaKit/Pods-BuildaKit.debug.xcconfig"; sourceTree = "