Giter VIP home page Giter VIP logo

octokit.swift's Introduction

Octokit.swift

CocoaPods

Installation

import PackageDescription

let package = Package(
  name: "MyAwesomeApp",
    dependencies: [
      .package(url: "https://github.com/nerdishbynature/octokit.swift", from: "0.11.0"),
    ]
  )

Authentication

Octokit supports both, GitHub and GitHub Enterprise. Authentication is handled using Configurations.

There are two types of Configurations, TokenConfiguration and OAuthConfiguration.

TokenConfiguration

TokenConfiguration is used if you are using Access Token based Authentication (e.g. the user offered you an access token he generated on the website) or if you got an Access Token through the OAuth Flow

You can initialize a new config for github.com as follows:

let config = TokenConfiguration("YOUR_PRIVATE_GITHUB_TOKEN_HERE")

or for GitHub Enterprise

let config = TokenConfiguration("YOUR_PRIVATE_GITHUB_TOKEN_HERE", url: "https://github.example.com/api/v3/")

After you got your token you can use it with Octokit

Octokit(config).me() { response in
  switch response {
  case .success(let user):
    print(user.login as Any)
  case .failure(let error):
    print(error)
  }
}

OAuthConfiguration

OAuthConfiguration is meant to be used, if you don't have an access token already and the user has to login to your application. This also handles the OAuth flow.

You can authenticate an user for github.com as follows:

let config = OAuthConfiguration(token: "<Your Client ID>", secret: "<Your Client secret>", scopes: ["repo", "read:org"])
let url = config.authenticate()

or for GitHub Enterprise

let config = OAuthConfiguration("https://github.example.com/api/v3/", webURL: "https://github.example.com/", token: "<Your Client ID>", secret: "<Your Client secret>", scopes: ["repo", "read:org"])

After you got your config you can authenticate the user:

// AppDelegate.swift

config.authenticate()

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
  config.handleOpenURL(url) { config in
    self.loadCurrentUser(config) // purely optional of course
  }
  return false
}

func loadCurrentUser(config: TokenConfiguration) {
  Octokit(config).me() { response in
    switch response {
    case .success(let user):
      print(user.login)
    case .failure(let error):
      print(error)
    }
  }
}

Please note that you will be given a TokenConfiguration back from the OAuth flow. You have to store the accessToken yourself. If you want to make further requests it is not necessary to do the OAuth Flow again. You can just use a TokenConfiguration.

let token = // get your token from your keychain, user defaults (not recommended) etc.
let config = TokenConfiguration(token)
Octokit(config).user(name: "octocat") { response in
  switch response {
  case .success(let user):
  	print("User login: \(user.login!)")
  case .failure(let error):
  	print("Error: \(error)")
  }
}

Users

Get a single user

let username = ... // set the username
Octokit().user(name: username) { response in
  switch response {
    case .success(let user):
      // do something with the user
    case .failure(let error):
      // handle any errors
  }
}

Get the authenticated user

Octokit().me() { response in
  switch response {
    case .success(let user):
      // do something with the user
    case .failure(let error):
      // handle any errors
  }

Repositories

Get a single repository

let (owner, name) = ("owner", "name") // replace with actual owner and name
Octokit().repository(owner, name) { response in
  switch response {
    case .success(let repository):
      // do something with the repository
    case .failure(let error):
      // handle any errors
  }
}

Get repositories of authenticated user

Octokit().repositories() { response in
  switch response {
    case .success(let repository):
      // do something
    case .failure(let error):
      // handle any errors
  }
}

Starred Repositories

Get starred repositories of some user

let username = "username"
Octokit().stars(username) { response in
  switch response {
    case .success(let repositories):
      // do something with the repositories
    case .failure(let error):
      // handle any errors
  }
}

Get starred repositories of authenticated user

Octokit().myStars() { response in
  switch response {
    case .success(let repositories):
      // do something with the repositories
    case .failure(let error):
      // handle any errors
  }
}

Follower and Following

Get followers of some user

let username = "username"
Octokit().followers(username) { response in
  switch response {
    case .success(let users):
      // do something with the users
    case .failure(let error):
      // handle any errors
  }
}

Get followers of authenticated user

Octokit().myFollowers() { response in
  switch response {
    case .success(let users):
      // do something with the users
    case .failure(let error):
      // handle any errors
  }
}

Get following of some user

let username = "username"
Octokit().following(username) { response in
  switch response {
    case .success(let users):
      // do something with the users
    case .failure(let error):
      // handle any errors
  }
}

Get following of authenticated user

Octokit().myFollowing() { response in
  switch response {
    case .success(let users):
      // do something with the users
    case .failure(let error):
      // handle any errors
  }
}

Issues

Get issues of authenticated user

Get all issues across all the authenticated user's visible repositories including owned repositories, member repositories, and organization repositories.

Octokit(config).myIssues() { response in
    switch response {
        case .success(let issues):
        // do something with the issues
    case .failure:
        // handle any errors
    }   
}

Get a single issue

let (owner, repo, number) = ("owner", "repo", 1347) // replace with actual owner, repo name, and issue number
Octokit(config).issue(owner, repository: repo, number: number) { response in
    switch response {
    case .success(let issue):
        // do something with the issue
    case .failure:
        // handle any errors
    }
}

Open a new issue

Octokit(config).postIssue("owner", repository: "repo", title: "Found a bug", body: "I'm having a problem with this.", assignee: "octocat", labels: ["bug", "duplicate"]) { response in
    switch response {
    case .success(let issue):
        // do something with the issue
    case .failure:
        // handle any errors
    }
}

Edit an existing issue

Octokit(config).patchIssue("owner", repository: "repo", number: 1347, title: "Found a bug", body: "I'm having a problem with this.", assignee: "octocat", state: .Closed) { response in
    switch response {
    case .success(let issue):
        // do something with the issue
    case .failure:
        // handle any errors
    }
}

Comment an issue

Octokit().commentIssue(owner: "octocat", repository: "Hello-World", number: 1, body: "Testing a comment") { response in
    switch response {
    case .success(let comment):
        // do something with the comment
    case .failure:
        // handle any errors
    }
}

Edit an existing comment

Octokit().patchIssueComment(owner: "octocat", repository: "Hello-World", number: 1, body: "Testing a comment") { response in
    switch response {
    case .success(let comment):
        // do something with the comment
    case .failure:
        // handle any errors
    }
}

Pull requests

Get a single pull request

Octokit().pullRequest(owner: "octocat", repository: "Hello-World", number: 1) { response in
    switch response {
        case .success(let pullRequests):
            // do something with a pull request
        case .failure:
            // handle any errors
     }
}

List pull requests

Octokit().pullRequests(owner: "octocat", repository: "Hello-World", base: "develop", state: Openness.Open) { response in
    switch response {
        case .success(let pullRequests):
        // do something with a pull request list
        case .failure:
        // handle any errors
    }
}

Update an exisiting Pull Request

Octokit().patchPullRequest(session, owner: "octocat", repository: "Hello-World", number: 1, title: "Updated title", body: "The updated body", state: .open, base: "base-branch", mantainerCanModify: true) { response in
    switch response {
        case .success(let pullrequest):
        // do something with the pullrequest
        case .failure:
        // handle any errors
    }
}

Releases

Create a new release

Octokit().postRelease(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
	switch response {
        case .success(let release):
        // do something with the release
        case .failure:
        // handle any errors
    }
}

octokit.swift's People

Contributors

1ec5 avatar 417-72ki avatar ambientlight avatar avdlee avatar dato avatar daybysay avatar dependabot[bot] avatar ellneal avatar f-meloni avatar kolyasev avatar lucascodert avatar mat avatar matheusalano avatar matiasvillaverde avatar maxdesiatov avatar muhdmirzamz avatar mvolpato avatar nwest avatar orta avatar petrpavlik avatar phatblat avatar pietbrauer avatar ps2 avatar robmathers avatar rubiojr avatar sfaxon avatar skywinder avatar thomaspaulmann avatar vincode-io avatar vinnyt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

octokit.swift's Issues

Issues API Calls

  • GET /issues
  • GET /user/issues
  • GET /orgs/:org/issues
  • GET /repos/:owner/:repo/issues
  • GET /repos/:owner/:repo/issues/:number
  • POST /repos/:owner/:repo/issues
  • PATCH /repos/:owner/:repo/issues/:number
  • PUT /repos/:owner/:repo/issues/:number/lock
  • DELETE /repos/:owner/:repo/issues/:number/lock
  • GET /repos/:owner/:repo/assignees
  • GET /repos/:owner/:repo/issues/:number/comments
  • GET /repos/:owner/:repo/issues/comments
  • GET /repos/:owner/:repo/issues/comments/:id
  • POST /repos/:owner/:repo/issues/:number/comments
  • PATCH /repos/:owner/:repo/issues/comments/:id
  • DELETE /repos/:owner/:repo/issues/comments/:id1
  • GET /repos/:owner/:repo/issues/:issue_number/events
  • GET /repos/:owner/:repo/issues/events
  • GET /repos/:owner/:repo/issues/events/:id
  • GET /repos/:owner/:repo/labels
  • GET /repos/:owner/:repo/labels/:name1
  • POST /repos/:owner/:repo/labels
  • PATCH /repos/:owner/:repo/labels/:name
  • DELETE /repos/:owner/:repo/labels/:name
  • GET /repos/:owner/:repo/issues/:number/labels
  • POST /repos/:owner/:repo/issues/:number/labels
  • DELETE /repos/:owner/:repo/issues/:number/labels/:name
  • PUT /repos/:owner/:repo/issues/:number/labels
  • DELETE /repos/:owner/:repo/issues/:number/labels
  • GET /repos/:owner/:repo/milestones/:number/labels
  • GET /repos/:owner/:repo/milestones
  • GET /repos/:owner/:repo/milestones/:number
  • POST /repos/:owner/:repo/milestones
  • PATCH /repos/:owner/:repo/milestones/:number
  • DELETE /repos/:owner/:repo/milestones/:number

Download repo ...

Great project ... is there anything on the horizon to add downloading a repo - getting list of contents (like a zip archive) and optionally d/l the repo to a given folder location ?

Support for Pull Requests + Issues

Do you have any plans to support Pull Requests and Issues? In particular, the topics that are related to a specific user, so f.e. all Pull Request of User XY.

Access token query parameter is deprecated

Please use the Authorization HTTP header instead, as using the access_token query parameter is deprecated.

As mentioned by GitHub. It's no longer recommended to use this together with the GitHub API. It's recommended to change code by making use of an Authentication header instead.

For example:

let configuration = URLSessionConfiguration.default
let username = "<github_username>"
let token = "<github_access_token>"
let authorizationToken = "\(username):\(token)".data(using: .utf8)!.base64EncodedString()
configuration.httpAdditionalHeaders = ["Authorization": "Basic \(token)"]
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)

Obviously, it would be nicer to integrate this into OctoKit for implementers to easily use.

Repositories tags

Is there a way to fetch a repository tags? I'm not finding anything about tags other than the Releases tagName

Issue with `patchIssue`

Hey, I just came across the following problem (hope this is not an application fault).

I want to close an issue using the async throws patchIssue function as shown in the README. However I keep on getting the following error:

typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "closed_at", intValue: nil)], debugDescription: "Expected to decode Double but found a string instead.", underlyingError: nil))

My code snippet:

   func close(issue: Issue) async throws {
        guard let github = github else { throw state }

        // no idea if this is necessary at all - won't work with and without
        issue.closedAt = Date()
        issue.closedBy = try await github.me()

         _ = try await github.patchIssue(owner: owner, repository: repo, number: issue.number, state: .closed)
    }

Any help appreciated, thanks.

Unauthorised with fetching repos with config

            let config = TokenConfiguration(GITHUB_TOKEN)
            let gh = Octokit(config)
            gh.repository(owner: owner, name: name) { response in
              switch response {
              case .success(let repository):
                stars = repository.stargazersCount
                if let unwrapped = stars {
                    print("\(name) : \(unwrapped)⭐️")
                }
                break
              case .failure(let error):
                print(error)
                break
   
              }

this code works fine without token (but with token gets error:

Error Domain=com.nerdishbynature.octokit Code=401 "(null)" UserInfo={RequestKitErrorKey={
    "documentation_url" = "https://developer.github.com/v3";
    message = "Bad credentials";
}}

I tried to send the same token by curl - everything works fine.

Deprecated function in README.md

Hi there! First of all, thanks for awesome framework!

func application(application: UIApplication, openURL url: NSURL,  sourceApplication: String?, annotation: AnyObject?) -> Bool

This function is deprecated, what should we use?

Upload Assets

Hi!

First off, thanks for the great tool 🎉

I have successfully automated a github release, but I can't find any way how to upload an asset - is this supported?
(I am talking about this endpoint)

If not, I can give a helping hand and try to take a stab at it 🔪

Tree and Refs API Calls

I'm planning to do a PR for refs and trees (then eventually files). Thought I'd share my plan and get any feedback. Here is the draft interface for trees (refs should be straightforward), the unique bit might be in how the tree structure gets returned. Composing the objects into a tree is an extra step that makes sense to me, but doesn't mirror the API response, so I'm interested to hear your thoughts.

Also, I'm wondering if truncated trees should be treated as an error response, it could certainly just be a property on the Tree object but it feels like its an error to not more explicitly handle it, I could see using a TreeResponse enum with the response case of Truncated that still passes along the tree.

/**
Getting a tree
- parameter owner: The user or organization that owns the repository.
- parameter repository: The name of the repository.
- parameter sha: sha of the commit to get the tree from
- parameter recursively: If true, composes the Tree's subdirectories in the Tree's entries property
- parameter completion: Callback for the outcome of the fetch. 
    Completion is called with a root Tree object that has an array property entries: [Tree]? 
    If recursive is true, subdirectories will have further Tree objects in their entries 
*/
func tree(owner: String, 
           repository: String, 
           sha: String, 
           recursively: Bool, 
           completion: (response: Response<Tree>) -> Void)

OAuth issue

Hi,

Big fan of this project. One problem though, I have tried the OAuth config settings and gotten the code attribute. I followed the code example you provided in the README.md but printing out user.login does not work. Mind helping me out here?

"Invalid URL string" exception when retrieving all the issues from a repo

⚠️ Pretty new to Swift, so it's certainly possible the following doesn't make sense at all...

Sample code:

import OctoKit
import Foundation

let config = TokenConfiguration("secret")
var done = false
let client = Octokit(config)

client.issues(owner: "rubiojr", repository: "test") { response in
    switch response {
    case .success(let issues):
        print(issues[0].labelsURL!)
    case .failure(let error):
        print(error)
    }
    done = true
}

repeat {
    RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
} while !done

The exception:

Compile Swift Module 'OctoKit' (14 sources)
Compile Swift Module 'labbelier' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/labbelier
dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "labels_url", intValue: nil)], debugDescription: "Invalid URL string.", underlyingError: nil))

I believe this happens because it may return something like https://api.github.com/repos/rubiojr/test/issues/3/labels{/name} as the value of labels_url (see https://developer.github.com/v3/issues/#list-issues-for-a-repository) and URL doesn't like that? Something like:

import Foundation

struct Example: Decodable {
    let url: URL?
}

let foo = try JSONDecoder().decode(Example.self, from: """
    { "url": "https://api.github.com/repos/rubiojr/test/issues/3/labels{/name}" }
    """.data(using: .utf8)!)

Causes:

Fatal error: Error raised at top level: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "url", intValue: nil)], debugDescription: "Invalid URL string.", underlyingError: nil)): file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang_Fall2018/swiftlang_Fall2018-1000.11.42/src/swift/stdlib/public/core/ErrorType.swift, line 191

As a workaround, I'm using a local copy of the lib changing

open var labelsURL: URL?
to use a String? instead, which seems to be working as expected but, is there a better way?

swift --version
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0

List PRs in Private Repos

Hi,

I can't seem to get the PRs in private repos and get the error:

Error Domain=com.nerdishbynature.octokit Code=404 "(null)" UserInfo={RequestKitErrorKey={ "documentation_url" = "https://docs.github.com/rest/reference/pulls#list-pull-requests"; message = "Not Found"; }}

I've given the repo scope and feel it should be working.

Any help would be appreciated!
Usman

How to disable caching?

I'm using Octokit(config).pullRequests(owner: , repository: )
but if I make a change in my Github PR it doesn't fetch the new data when called.
Looks like it is caching the response for a while.

Is there any way to disable this, and always fetch from a fresh api call?

:/

hi ,sorry bro but your app dont run :\

Cannot run Unit Test due to missing JSON mocks

Hi,

I have cloned this repo and I have tried running it in Xcode but the included Unit Tests does not pass due to multiple missing JSON files. For example test FollowTests.testGetMyFollowers()

fails due to:

Fatal error: Unexpectedly found nil while unwrapping an Optional value
2019-05-09 14:25:44.158687+0200 xctest[47127:288344] Fatal error: Unexpectedly found nil while unwrapping an Optional value

the unit test is looking for a JSON file named users but this file is not included in the repo (I am using master branch).

I am running octokit.swift library on macOS Mojave 10.14.4 (18E227)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.