From e94d5d87124724f520b0e5d46656674a087df6be Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Tue, 8 Mar 2016 10:27:03 +0800 Subject: [PATCH 1/4] Add support for merge requests --- TanukiKit.xcodeproj/project.pbxproj | 22 +++++ TanukiKit/MergeRequests.swift | 97 +++++++++++++++++++++ TanukiKitTests/Fixtures/merge_requests.json | 62 +++++++++++++ TanukiKitTests/MergeRequestsTests.swift | 57 ++++++++++++ TanukiKitTests/TestHelper.swift | 14 +++ 5 files changed, 252 insertions(+) create mode 100644 TanukiKit/MergeRequests.swift create mode 100644 TanukiKitTests/Fixtures/merge_requests.json create mode 100644 TanukiKitTests/MergeRequestsTests.swift diff --git a/TanukiKit.xcodeproj/project.pbxproj b/TanukiKit.xcodeproj/project.pbxproj index 7dd6c59..7da30d0 100644 --- a/TanukiKit.xcodeproj/project.pbxproj +++ b/TanukiKit.xcodeproj/project.pbxproj @@ -20,6 +20,14 @@ 233A0B311C0EFE0400072A58 /* Nocilla.framework in Carthage embed */ = {isa = PBXBuildFile; fileRef = 233A0B2E1C0EFDDC00072A58 /* Nocilla.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 233A0B321C0EFE0400072A58 /* RequestKit.framework in Carthage embed */ = {isa = PBXBuildFile; fileRef = 233A0B2C1C0EFDD000072A58 /* RequestKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 233A0B341C0EFE2A00072A58 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233A0B331C0EFE2A00072A58 /* ConfigurationTests.swift */; }; + 23676DF91C8E64D100184E1D /* MergeRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DF81C8E64D100184E1D /* MergeRequests.swift */; }; + 23676DFB1C8E678900184E1D /* MergeRequestsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DFA1C8E678900184E1D /* MergeRequestsTests.swift */; }; + 23676DFC1C8E678F00184E1D /* MergeRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DF81C8E64D100184E1D /* MergeRequests.swift */; }; + 23676DFD1C8E678F00184E1D /* MergeRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DF81C8E64D100184E1D /* MergeRequests.swift */; }; + 23676DFE1C8E679000184E1D /* MergeRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DF81C8E64D100184E1D /* MergeRequests.swift */; }; + 23676DFF1C8E679300184E1D /* MergeRequestsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DFA1C8E678900184E1D /* MergeRequestsTests.swift */; }; + 23676E001C8E679400184E1D /* MergeRequestsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23676DFA1C8E678900184E1D /* MergeRequestsTests.swift */; }; + 23676E021C8E67E800184E1D /* merge_requests.json in Resources */ = {isa = PBXBuildFile; fileRef = 23676E011C8E67E800184E1D /* merge_requests.json */; }; 23A4CE041C7C6BDF00261CFB /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233A0B1D1C0EF94400072A58 /* Configuration.swift */; }; 23A4CE051C7C6BDF00261CFB /* GitLabKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233A0B1E1C0EF94400072A58 /* GitLabKit.swift */; }; 23A4CE061C7C6BDF00261CFB /* Repositories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233A0B1F1C0EF94400072A58 /* Repositories.swift */; }; @@ -145,6 +153,9 @@ 233A0B2C1C0EFDD000072A58 /* RequestKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RequestKit.framework; path = ../Carthage/Build/iOS/RequestKit.framework; sourceTree = ""; }; 233A0B2E1C0EFDDC00072A58 /* Nocilla.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nocilla.framework; path = ../Carthage/Build/iOS/Nocilla.framework; sourceTree = ""; }; 233A0B331C0EFE2A00072A58 /* ConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; + 23676DF81C8E64D100184E1D /* MergeRequests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergeRequests.swift; sourceTree = ""; }; + 23676DFA1C8E678900184E1D /* MergeRequestsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergeRequestsTests.swift; sourceTree = ""; }; + 23676E011C8E67E800184E1D /* merge_requests.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = merge_requests.json; path = Fixtures/merge_requests.json; sourceTree = ""; }; 23A4CDFC1C7C6BD700261CFB /* TanukiKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TanukiKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23A4CE0F1C7C6BF700261CFB /* TanukiKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TanukiKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23A4CE181C7C6BF700261CFB /* TanukiKit tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TanukiKit tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -257,6 +268,7 @@ 233A0B1F1C0EF94400072A58 /* Repositories.swift */, 23FC28DA1C1AD8AB0017CBDA /* Keys.swift */, 233A0B201C0EF94400072A58 /* User.swift */, + 23676DF81C8E64D100184E1D /* MergeRequests.swift */, 233A0B081C0EF8E900072A58 /* Info.plist */, ); path = TanukiKit; @@ -269,6 +281,7 @@ 233A0B141C0EF8E900072A58 /* Info.plist */, 233A0B331C0EFE2A00072A58 /* ConfigurationTests.swift */, 23FC28DC1C1AD8FD0017CBDA /* KeysTests.swift */, + 23676DFA1C8E678900184E1D /* MergeRequestsTests.swift */, 23FC28DE1C1AD9680017CBDA /* TestHelper.swift */, 23523FFA1C0F0CE100216E20 /* Frameworks */, ); @@ -281,6 +294,7 @@ 233A0B281C0EFDBC00072A58 /* Repositories.json */, 233A0B291C0EFDBC00072A58 /* User.json */, 23FC28E01C1AD9DD0017CBDA /* public_key.json */, + 23676E011C8E67E800184E1D /* merge_requests.json */, ); name = Fixtures; sourceTree = ""; @@ -543,6 +557,7 @@ files = ( 23FC28E11C1AD9DD0017CBDA /* public_key.json in Resources */, 233A0B2B1C0EFDBC00072A58 /* User.json in Resources */, + 23676E021C8E67E800184E1D /* merge_requests.json in Resources */, 233A0B2A1C0EFDBC00072A58 /* Repositories.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -599,6 +614,7 @@ 233A0B211C0EF94400072A58 /* Configuration.swift in Sources */, 233A0B221C0EF94400072A58 /* GitLabKit.swift in Sources */, 233A0B231C0EF94400072A58 /* Repositories.swift in Sources */, + 23676DF91C8E64D100184E1D /* MergeRequests.swift in Sources */, 23FC28DB1C1AD8AB0017CBDA /* Keys.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -609,6 +625,7 @@ files = ( 23FC28DF1C1AD9680017CBDA /* TestHelper.swift in Sources */, 233A0B341C0EFE2A00072A58 /* ConfigurationTests.swift in Sources */, + 23676DFB1C8E678900184E1D /* MergeRequestsTests.swift in Sources */, 23FC28DD1C1AD8FD0017CBDA /* KeysTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -621,6 +638,7 @@ 23A4CE051C7C6BDF00261CFB /* GitLabKit.swift in Sources */, 23A4CE061C7C6BDF00261CFB /* Repositories.swift in Sources */, 23A4CE071C7C6BDF00261CFB /* Keys.swift in Sources */, + 23676DFC1C8E678F00184E1D /* MergeRequests.swift in Sources */, 23A4CE081C7C6BDF00261CFB /* User.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -633,6 +651,7 @@ 23A4CE271C7C6BFD00261CFB /* GitLabKit.swift in Sources */, 23A4CE281C7C6BFD00261CFB /* Repositories.swift in Sources */, 23A4CE291C7C6BFD00261CFB /* Keys.swift in Sources */, + 23676DFD1C8E678F00184E1D /* MergeRequests.swift in Sources */, 23A4CE2A1C7C6BFD00261CFB /* User.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -643,6 +662,7 @@ files = ( 23A4CE2C1C7C6C3600261CFB /* ConfigurationTests.swift in Sources */, 23A4CE2D1C7C6C3600261CFB /* KeysTests.swift in Sources */, + 23676DFF1C8E679300184E1D /* MergeRequestsTests.swift in Sources */, 23A4CE2E1C7C6C3600261CFB /* TestHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -655,6 +675,7 @@ 23A4CE4C1C7C6C5D00261CFB /* GitLabKit.swift in Sources */, 23A4CE4D1C7C6C5D00261CFB /* Repositories.swift in Sources */, 23A4CE4E1C7C6C5D00261CFB /* Keys.swift in Sources */, + 23676DFE1C8E679000184E1D /* MergeRequests.swift in Sources */, 23A4CE4F1C7C6C5D00261CFB /* User.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -665,6 +686,7 @@ files = ( 23A4CE511C7C6C7D00261CFB /* ConfigurationTests.swift in Sources */, 23A4CE521C7C6C7D00261CFB /* KeysTests.swift in Sources */, + 23676E001C8E679400184E1D /* MergeRequestsTests.swift in Sources */, 23A4CE531C7C6C7D00261CFB /* TestHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TanukiKit/MergeRequests.swift b/TanukiKit/MergeRequests.swift new file mode 100644 index 0000000..3ba6d3d --- /dev/null +++ b/TanukiKit/MergeRequests.swift @@ -0,0 +1,97 @@ +import Foundation +import RequestKit + +// MARK: model +@objc public class MergeRequest: NSObject { + public var id: Int + public var title: String? = nil + public var mergeRequestDescription: String? + public var author: User? = nil + public var mergeStatus: String? + public var projectID: Int? + public var sourceBranch: String? + public var sourceProjectID: Int? + public var targetBranch: String? + public var targetProjectID: Int? + public var workInProgress: Bool? + + public init(_ json: [String: AnyObject]) { + if let authorJSON = json["author"] as? [String: AnyObject] { + self.author = User(authorJSON) + } + if let id = json["id"] as? Int { + self.id = id + self.title = json["title"] as? String + self.mergeRequestDescription = json["description"] as? String + self.mergeStatus = json["merge_status"] as? String + self.projectID = json["project_id"] as? Int + self.sourceBranch = json["source_branch"] as? String + self.sourceProjectID = json["source_project_id"] as? Int + self.targetBranch = json["target_branch"] as? String + self.workInProgress = json["work_in_progress"] as? Bool + self.targetProjectID = json["target_project_id"] as? Int + } else { + self.id = -1 + } + } +} + +extension MergeRequest { + +} + +// MARK: request + +public extension TanukiKit { + /** + Fetches the open merg requests for the owner/repo combination + - parameter completion: Callback for the outcome of the fetch. + */ + public func mergeRequests(repoID: String, page: String = "1", perPage: String = "100", completion: (response:Response<[MergeRequest]>) -> Void) { + let router = MergeRequestsRouter.ReadMergeRequests(configuration, repoID, page, perPage) + router.loadJSON([[String: AnyObject]].self) { json, error in + if let error = error { + completion(response: Response.Failure(error)) + } else { + if let json = json { + let mergeRequests = json.map { MergeRequest($0) } + completion(response: Response.Success(mergeRequests)) + } + } + } + } +} + +// MARK: Router + +enum MergeRequestsRouter: Router { + case ReadMergeRequests(Configuration, String, String, String) + + var configuration: Configuration { + switch self { + case .ReadMergeRequests(let config, _, _, _): return config + } + } + + var method: HTTPMethod { + return .GET + } + + var encoding: HTTPEncoding { + return .URL + } + + var params: [String: String] { + switch self { + case .ReadMergeRequests(_, _, let page, let perPage): + return ["per_page": perPage, "page": page] + } + } + + var path: String { + switch self { + case .ReadMergeRequests(_, let repoID, _, _): + return "/projects/\(repoID)/merge_requests" + } + } +} diff --git a/TanukiKitTests/Fixtures/merge_requests.json b/TanukiKitTests/Fixtures/merge_requests.json new file mode 100644 index 0000000..f46af22 --- /dev/null +++ b/TanukiKitTests/Fixtures/merge_requests.json @@ -0,0 +1,62 @@ +[ + { + "assignee": null, + "author": { + "avatar_url": "https://secure.gravatar.com/avatar/1856b6db24ec5ff8d534726de2d75f13?s=80&d=identicon", + "id": 61673, + "name": "Piet Brauer", + "state": "active", + "username": "pietbrauer", + "web_url": "https://gitlab.com/u/pietbrauer" + }, + "created_at": "2016-03-08T02:03:30.211Z", + "description": "", + "downvotes": 0, + "id": 354284, + "iid": 2, + "labels": [], + "merge_status": "can_be_merged", + "merge_when_build_succeeds": false, + "milestone": null, + "project_id": 639042, + "source_branch": "test-images", + "source_project_id": 945182, + "state": "opened", + "target_branch": "master", + "target_project_id": 639042, + "title": "Add star", + "updated_at": "2016-03-08T02:03:30.211Z", + "upvotes": 0, + "work_in_progress": false + }, + { + "assignee": null, + "author": { + "avatar_url": "https://secure.gravatar.com/avatar/1856b6db24ec5ff8d534726de2d75f13?s=80&d=identicon", + "id": 61673, + "name": "Piet Brauer", + "state": "active", + "username": "pietbrauer", + "web_url": "https://gitlab.com/u/pietbrauer" + }, + "created_at": "2016-03-08T01:56:02.203Z", + "description": "## Some headline\r\n\r\n* This\r\n* is\r\n* a\r\n* test", + "downvotes": 0, + "id": 354274, + "iid": 1, + "labels": [], + "merge_status": "can_be_merged", + "merge_when_build_succeeds": false, + "milestone": null, + "project_id": 639042, + "source_branch": "release_testing", + "source_project_id": 639042, + "state": "opened", + "target_branch": "master", + "target_project_id": 639042, + "title": "Release testing", + "updated_at": "2016-03-08T01:56:02.203Z", + "upvotes": 0, + "work_in_progress": false + } +] diff --git a/TanukiKitTests/MergeRequestsTests.swift b/TanukiKitTests/MergeRequestsTests.swift new file mode 100644 index 0000000..8f5ae52 --- /dev/null +++ b/TanukiKitTests/MergeRequestsTests.swift @@ -0,0 +1,57 @@ +import XCTest +import TanukiKit +import Nocilla + +class MergeRequestsTests: XCTestCase { + override func setUp() { + super.setUp() + LSNocilla.sharedInstance().start() + } + + override func tearDown() { + super.tearDown() + LSNocilla.sharedInstance().clearStubs() + LSNocilla.sharedInstance().stop() + } + + func testJSONParsing() { + let json = (TestHelper.loadJSON("merge_requests") as! [[String: AnyObject]]).first! + + let subject = MergeRequest(json) + XCTAssertEqual(subject.title, "Add star") + XCTAssertEqual(subject.mergeRequestDescription, "") + XCTAssertEqual(subject.author?.name, "Piet Brauer") + XCTAssertEqual(subject.mergeStatus, "can_be_merged") + XCTAssertEqual(subject.projectID, 639042) + XCTAssertEqual(subject.sourceBranch, "test-images") + XCTAssertEqual(subject.sourceProjectID, 945182) + XCTAssertEqual(subject.targetBranch, "master") + XCTAssertEqual(subject.targetProjectID, 639042) + XCTAssertFalse(subject.workInProgress ?? true) + } + + // MARK: Actual Request tests + + func testPostPublicKey() { + let config = PrivateTokenConfiguration("12345") + if let json = TestHelper.stringFromFile("merge_requests") { + stubRequest("GET", "https://gitlab.com/api/v3/projects/1234/merge_requests?page=1&per_page=100&private_token=12345").andReturn(200).withHeaders(["Content-Type": "application/json"]).withBody(json) + let expectation = expectationWithDescription("public_key") + TanukiKit(config).mergeRequests("1234") { response in + switch response { + case .Success(let mergeRequests): + XCTAssertEqual(mergeRequests.count, 2) + expectation.fulfill() + case .Failure: + XCTAssert(false, "should not get an error") + expectation.fulfill() + } + } + waitForExpectationsWithTimeout(1) { (error) in + XCTAssertNil(error, "\(error)") + } + } else { + XCTFail("json shouldn't be nil") + } + } +} diff --git a/TanukiKitTests/TestHelper.swift b/TanukiKitTests/TestHelper.swift index 2f71988..e1c08a0 100644 --- a/TanukiKitTests/TestHelper.swift +++ b/TanukiKitTests/TestHelper.swift @@ -10,4 +10,18 @@ internal class TestHelper { } return nil } + + static func loadJSON(name: String) -> AnyObject? { + let bundle = NSBundle(forClass: self) + let path = bundle.pathForResource(name, ofType: "json") + if let path = path, data = NSData(contentsOfFile: path) { + let json: AnyObject? = try? NSJSONSerialization.JSONObjectWithData(data, + options: NSJSONReadingOptions.MutableContainers) + if let json = json { + return json + } + } + + return nil + } } \ No newline at end of file From 471ab84c1230b783988df44a4017fa24c2b5110e Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Tue, 8 Mar 2016 10:28:00 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=9A=AB=F0=9F=93=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d8b8431..fa2431f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,3 +26,5 @@ after_success: - if [ "$FASTLANE_LANE" == "code_coverage" ]; then make post_coverage; fi +notifications: + email: false From 6f6a4b18ae818aa3f904248744b963b792dade36 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Tue, 8 Mar 2016 10:28:07 +0800 Subject: [PATCH 3/4] Ignore fastlane download --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 89940e3..0383eba 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ DerivedData Pods/ Carthage/ Checkouts/ +fastlane/test-output/ +fastlane/README.md +fastlane/report.xml From 4299ee2daf0e4c4cec8bb92fd5666e347fa15c7d Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Tue, 8 Mar 2016 11:54:56 +0800 Subject: [PATCH 4/4] Inclusion is king --- TanukiKit.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TanukiKit.xcodeproj/project.pbxproj b/TanukiKit.xcodeproj/project.pbxproj index 7da30d0..43f5a62 100644 --- a/TanukiKit.xcodeproj/project.pbxproj +++ b/TanukiKit.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ 23A4CE691C7C6E8600261CFB /* Nocilla.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23A4CE681C7C6E8600261CFB /* Nocilla.framework */; }; 23A4CE6A1C7C6E8C00261CFB /* Nocilla.framework in Carthage embed */ = {isa = PBXBuildFile; fileRef = 23A4CE681C7C6E8600261CFB /* Nocilla.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 23A4CE6B1C7C6E8F00261CFB /* RequestKit.framework in Carthage embed */ = {isa = PBXBuildFile; fileRef = 23A4CE651C7C6E6E00261CFB /* RequestKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 23AA53B91C8E847E00368282 /* merge_requests.json in Resources */ = {isa = PBXBuildFile; fileRef = 23676E011C8E67E800184E1D /* merge_requests.json */; }; + 23AA53BA1C8E847E00368282 /* merge_requests.json in Resources */ = {isa = PBXBuildFile; fileRef = 23676E011C8E67E800184E1D /* merge_requests.json */; }; 23FC28DB1C1AD8AB0017CBDA /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23FC28DA1C1AD8AB0017CBDA /* Keys.swift */; }; 23FC28DD1C1AD8FD0017CBDA /* KeysTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23FC28DC1C1AD8FD0017CBDA /* KeysTests.swift */; }; 23FC28DF1C1AD9680017CBDA /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23FC28DE1C1AD9680017CBDA /* TestHelper.swift */; }; @@ -582,6 +584,7 @@ files = ( 23A4CE571C7C6C8500261CFB /* Repositories.json in Resources */, 23A4CE581C7C6C8500261CFB /* User.json in Resources */, + 23AA53B91C8E847E00368282 /* merge_requests.json in Resources */, 23A4CE591C7C6C8500261CFB /* public_key.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -599,6 +602,7 @@ files = ( 23A4CE541C7C6C8100261CFB /* Repositories.json in Resources */, 23A4CE551C7C6C8100261CFB /* User.json in Resources */, + 23AA53BA1C8E847E00368282 /* merge_requests.json in Resources */, 23A4CE561C7C6C8100261CFB /* public_key.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0;