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

Implement the API endpoint for listing releases #116

Merged
merged 5 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions OctoKit/Releases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public struct Release: Codable {
public let url: URL
public let htmlURL: URL
public let assetsURL: URL
public let tarballURL: URL
public let zipballURL: URL
public let tarballURL: URL?
public let zipballURL: URL?
pietbrauer marked this conversation as resolved.
Show resolved Hide resolved
public let nodeId: String
public let tagName: String
public let commitish: String
Expand All @@ -28,7 +28,7 @@ public struct Release: Codable {
public let draft: Bool
public let prerelease: Bool
public let createdAt: Date
public let publishedAt: Date
public let publishedAt: Date?
pietbrauer marked this conversation as resolved.
Show resolved Hide resolved
public let author: User

enum CodingKeys: String, CodingKey {
Expand All @@ -49,6 +49,25 @@ public struct Release: Codable {
// MARK: request

public extension Octokit {
/// Fetches the list of releases.
/// - Parameters:
/// - session: RequestKitURLSession, defaults to URLSession.shared()
/// - owner: The user or organization that owns the repositories.
/// - repository: The name of the repository.
/// - completion: Callback for the outcome of the fetch.
@discardableResult
func listReleases(_ session: RequestKitURLSession = URLSession.shared, owner: String, repository: String, completion: @escaping (_ response: Response<[Release]>) -> Void) -> URLSessionDataTaskProtocol? {
let router = ReleaseRouter.listReleases(configuration, owner, repository)
return router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: [Release].self) { releases, error in
Comment on lines +59 to +61
Copy link
Contributor

Choose a reason for hiding this comment

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

Diffs aren't automatically wrapped everywhere, so please avoid long lines, as it makes the code harder to review on devices without a wide screen. 100-120 characters line limit should be sufficient in most cases.

Copy link
Member

Choose a reason for hiding this comment

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

I agree that we should limit the lines to some amount of characters. I don’t know if 100-120 is the correct number but it should be enforced with some swiftformat/swiftlint rules so it applies everywhere for everyone.

I personally wouldn’t leave this as a mandatory change to get this PR accepted.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm aware of this one, and SwiftFormat recently also gained an ability to fit code into given line length too 🙂

if let error = error {
completion(Response.failure(error))
} else {
if let releases = releases {
completion(Response.success(releases))
}
}
}
}

/// Creates a new release.
/// - Parameters:
Expand Down Expand Up @@ -83,24 +102,38 @@ public extension Octokit {
// MARK: Router

enum ReleaseRouter: JSONPostRouter {
case listReleases(Configuration, String, String)
case postRelease(Configuration, String, String, String, String?, String?, String?, Bool, Bool)

var configuration: Configuration {
switch self {
case .listReleases(let config, _, _): return config
case .postRelease(let config, _, _, _, _, _, _, _, _): return config
}
}

var method: HTTPMethod {
return .POST
switch self {
case .listReleases:
return .GET
case .postRelease:
return .POST
}
}

var encoding: HTTPEncoding {
return .json
switch self {
case .listReleases:
return .url
case .postRelease:
return .json
}
}

var params: [String: Any] {
switch self {
case .listReleases:
return [:]
case .postRelease(_, _, _, let tagName, let targetCommitish, let name, let body, let prerelease, let draft):
var params: [String: Any] = [
"tag_name": tagName,
Expand All @@ -122,6 +155,8 @@ enum ReleaseRouter: JSONPostRouter {

var path: String {
switch self {
case let .listReleases(_, owner, repo):
return "repos/\(owner)/\(repo)/releases"
case .postRelease(_, let owner, let repo, _, _, _, _, _, _):
return "repos/\(owner)/\(repo)/releases"
}
Expand Down
80 changes: 80 additions & 0 deletions Tests/OctoKitTests/Fixtures/releases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
[
{
"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
"html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
"assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets",
"upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}",
"tarball_url": null,
"zipball_url": null,
"id": 1,
"node_id": "MDc6UmVsZWFzZTE=",
"tag_name": "v1.0.0",
"target_commitish": "master",
"name": "v1.0.0 Release",
"body": "The changelog of this release",
"draft": true,
"prerelease": false,
"created_at": "2013-02-27T19:35:32Z",
"published_at": null,
"author": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"assets": []
},
{
"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
"html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
"assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets",
"upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}",
"tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0",
"zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0",
"id": 1,
"node_id": "MDc6UmVsZWFzZTE=",
"tag_name": "v1.0.0",
"target_commitish": "master",
"name": "v1.0.0 Release",
"body": "The changelog of this release",
"draft": false,
"prerelease": false,
"created_at": "2013-02-27T19:35:32Z",
"published_at": "2013-02-27T19:35:32Z",
"author": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"assets": []
}
]
41 changes: 41 additions & 0 deletions Tests/OctoKitTests/ReleasesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,53 @@ import OctoKit

final class ReleasesTests: XCTestCase {
static var allTests = [
("testListReleases", testListReleases),
("testPostRelease", testPostRelease),
("testLinuxTestSuiteIncludesAllTests", testLinuxTestSuiteIncludesAllTests)
]

// MARK: Actual Request tests

func testListReleases() {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/releases", expectedHTTPMethod: "GET", jsonFile: "Fixtures/releases", statusCode: 200)
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: please split this to multiple lines to reduce the length of this line for easier review.

let task = Octokit().listReleases(session, owner: "octocat", repository: "Hello-World") {
switch $0 {
case let .success(releases):
XCTAssertEqual(releases.count, 2)
if let release = releases.first {
XCTAssertEqual(release.tagName, "v1.0.0")
XCTAssertEqual(release.commitish, "master")
XCTAssertEqual(release.name, "v1.0.0 Release")
XCTAssertEqual(release.body, "The changelog of this release")
XCTAssertFalse(release.prerelease)
XCTAssertTrue(release.draft)
XCTAssertNil(release.tarballURL)
XCTAssertNil(release.zipballURL)
XCTAssertNil(release.publishedAt)
} else {
XCTFail("Failed to unwrap `releases.first`")
}
if let release = releases.last {
XCTAssertEqual(release.tagName, "v1.0.0")
XCTAssertEqual(release.commitish, "master")
XCTAssertEqual(release.name, "v1.0.0 Release")
XCTAssertEqual(release.body, "The changelog of this release")
XCTAssertFalse(release.prerelease)
XCTAssertFalse(release.draft)
XCTAssertEqual(release.tarballURL?.absoluteString, "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0")
XCTAssertEqual(release.zipballURL?.absoluteString, "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0")
XCTAssertEqual(release.publishedAt, Date(timeIntervalSince1970: 1361993732.0))
} else {
XCTFail("Failed to unwrap `releases.last`")
}
case let .failure(error):
XCTAssert(false, "Endpoint failed with error \(error)")
}
}
XCTAssertNotNil(task)
XCTAssertTrue(session.wasCalled)
}

func testPostRelease() {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/octocat/Hello-World/releases", expectedHTTPMethod: "POST", jsonFile: "post_release", statusCode: 201)
let task = Octokit().postRelease(session, owner: "octocat", repository: "Hello-World", tagName: "v1.0.0", targetCommitish: "master", name: "v1.0.0 Release", body: "The changelog of this release", prerelease: false, draft: false) { response in
Expand Down