Giter VIP home page Giter VIP logo

tentacat's People

Contributors

achiurizo avatar aj-foster avatar bigardone avatar bryanhuntesl avatar daveshah avatar duksis avatar ebkh avatar edgurgel avatar ghedamat avatar iurifq avatar jeffweiss avatar joe-noh avatar jongretar avatar kianmeng avatar matsubara0507 avatar mbirman avatar milica-nerlovic avatar motet-a avatar niklaslong avatar outofambit avatar quinnwilton avatar reset avatar sandisk avatar sreecodeslayer avatar trenpixster avatar trodrigu avatar velimir avatar vermaxik avatar zamith avatar zorbash 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

tentacat's Issues

testing guide in the readme

Almost all software needs tests. This could therefore help a lot of people.
I agree with Jose that mocking is not the best solution (http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/) and therefore think a behaviour-based approach could work best. This means that we have one module which we can exchange in the test environment for another behaviour. Behaviours in elixir can be seen like inheritance in other languages.
So in our tests, we would probably have a genserver store the items (in an :ets-table ?) we need and return them if the business logic asks for them. In dev and production, the tentacat wrapper would ask the other behaviour which works as usual.

Another possibility would be to create a test package just like they are doing here: beam-community/stripity-stripe#124

I will try to find a solution within the next days and would love to get some input here. When I'm finished I'll make a PR to update the readme.

Name change

First of all, thanks for your interest in GitHub and creating a client library! However, the Octokit name is being used to represent officially supported libraries, so naming this library octokit could mislead users into thinking that it's a project by GitHub.

Would you mind changing the name to something other than Octokit? Thanks!

update httpoison

Is there a reason why not jump to httpoison 1.x?
If not, may I crete the pul request?

support passing in params for Deployments.list method

Looking at GitHub's Deployments api docs, it describes the ability to filter deployments by "sha", "ref", "task" and "environment". There doesn't seem to be the ability to pass in optional query params to the Tentacat.Repositories.Deployments.list call. This will be convenient, for instance, in the case of finding all deployments associated with a PR/sha value.

passing the etag in requests

Hi, I'm going to drop down to HTTPoison most likely for this, one optimization which can be made in any call is to pass the ETag from the previous invocation - if you do so, and nothing has changed, your rate limit remains unchanged. Could it be passed in the existing options block?

"ETag", ""eaa46eb91c77ded86b4261245e49fbd5"

response success tuple not returned

initially reported in #144 (comment)

it looks like some (possibly all) calls to get return the error tuple ({integer, any, HTTPoison.Response.t()}) instead of the success tuple ({:ok, :jsx.json_term(), HTTPoison.Response.t()}) on successful calls.

Unexpected failures running mix test

Hi!

Just wanting to start creating a PR to support searching for users (its something I am working on atm).

Have cloned repo locally, but when I run

MIX_ENV=test mix do deps.get, test

I get the following errors ๐Ÿ˜ž

1) test followers/2 (Tentacat.FollowersTest)
     test/followers_test.exs:33
     ** (CaseClauseError) no case clause matching: {:error, {:undef, [{:cover, :is_compiled, [:hackney], []}, {:meck_proc, :get_cover_state, 1, [file: 'src/meck_proc.erl', line: 395]}, {:meck_proc, :backup_original, 3, [file: 'src/meck_proc.erl', line: 350]}, {:meck_proc, :init, 1, [file: 'src/meck_proc.erl', line: 204]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}}
     stacktrace:
       src/meck_proc.erl:112: :meck_proc.set_expect/2
       src/meck.erl:234: :meck.expect/3
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/followers_test.exs:34

  2) test following?/3 (Tentacat.FollowersTest)
     test/followers_test.exs:45
     ** (CaseClauseError) no case clause matching: {:error, {:undef, [{:cover, :is_compiled, [:hackney], []}, {:meck_proc, :get_cover_state, 1, [file: 'src/meck_proc.erl', line: 395]}, {:meck_proc, :backup_original, 3, [file: 'src/meck_proc.erl', line: 350]}, {:meck_proc, :init, 1, [file: 'src/meck_proc.erl', line: 204]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}}
     stacktrace:
       src/meck_proc.erl:112: :meck_proc.set_expect/2
       src/meck.erl:234: :meck.expect/3
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/followers_test.exs:46

  3) test unfollow/2 (Tentacat.FollowersTest)
     test/followers_test.exs:57
     ** (CaseClauseError) no case clause matching: {:error, {:undef, [{:cover, :is_compiled, [:hackney], []}, {:meck_proc, :get_cover_state, 1, [file: 'src/meck_proc.erl', line: 395]}, {:meck_proc, :backup_original, 3, [file: 'src/meck_proc.erl', line: 350]}, {:meck_proc, :init, 1, [file: 'src/meck_proc.erl', line: 204]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}}
     stacktrace:
       src/meck_proc.erl:112: :meck_proc.set_expect/2
       src/meck.erl:234: :meck.expect/3
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/followers_test.exs:58

...a bunch more of the same errors go here....

 97) test delete/4 (Tentacat.Commits.CommentsTest)
     test/commits/comments_test.exs:55
     ** (CaseClauseError) no case clause matching: {:error, {:undef, [{:cover, :is_compiled, [:hackney], []}, {:meck_proc, :get_cover_state, 1, [file: 'src/meck_proc.erl', line: 395]}, {:meck_proc, :backup_original, 3, [file: 'src/meck_proc.erl', line: 350]}, {:meck_proc, :init, 1, [file: 'src/meck_proc.erl', line: 204]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}}
     stacktrace:
       src/meck_proc.erl:112: :meck_proc.set_expect/2
       src/meck.erl:234: :meck.expect/3
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/commits/comments_test.exs:56

..

Finished in 0.7 seconds (0.4s on load, 0.2s on tests)
105 tests, 97 failures, 7 invalid

This is my output from deps.get:

 MIX_ENV=test mix do deps.get, test
inch_ex is missing its version requirement, use ">= 0.0.0" if it should match any version
Running dependency resolution
Dependency resolution completed
  certifi: 0.3.0
  earmark: 0.1.19
  ex_doc: 0.8.4
  exactor: 2.2.0
  excoveralls: 0.4.5
  exjsx: 3.2.0
  exvcr: 0.7.1
  hackney: 1.4.8
  httpoison: 0.8.1
  idna: 1.0.3
  inch_ex: 0.4.0
  jsx: 2.6.2
  meck: 0.8.4
  mimerl: 1.0.2
  poison: 1.5.2
  ssl_verify_hostname: 1.0.5

New to elixir from ruby, so it might just be my setup, but not sure where to start looking. ๐Ÿ˜ƒ

Deserialization Options is wrong

Based on our Readme, if we want to use decode JSON, we can pass deserialization options following this way:

#To have Atom keys
config :tentacat, :deserialization_options, [labels: :atoms]

But seems like this one is outdated or just a typo with the current version of exjsx (4.0.0)
https://github.com/talentdeficit/exjsx#decodejson-opts

We have to pass a tuple, not a keyword list. cc @edgurgel please take a look at it if you have time, I will create a PR to fix this one.

Support for v4 GraphQL

Could be just basic but it'd be nice to be able to easily specify the query and the parameters w/ the client and have it run it for you. Something like:

Tentacat.GraphQL.query(@query, %{params: :go_here}, client)

404 for Tentacat.Organizations.Hooks.create()

Using Tentacat for a project and so far its worked wonderfully for almost everything. I'm finally running into an issue creating a new webhook for an organization.

client = Tentacat.Client.new(%{access_token: get_session(conn, :access_token)})
params = %{
  name: "web",
  active: true,
  config: %{
    url: Application.get_env(:my_app, GithubHooks)[:webhook_payload_uri],
    content_type: "json"
  },
  events: [
    "commit_comment",
    "create",
    "delete",
    "gollum",
    "issue_comment",
    "issues",
    "label",
    "milestone",
    "project_card",
    "project_column",
    "project",
    "public",
    "pull_request",
    "pull_request_review",
    "pull_request_review_comment",
    "release"
  ]
}
Tentacat.Organizations.Hooks.create("my_org", params, client)

Reponse I get back is:

{404,
 %{"documentation_url" => "https://developer.github.com/v3",
   "message" => "Not Found"}}

See anything obvious that I'm doing wrong?

URL Parameters

Trying to use Tentacat.Issues.list_all passing a since parameter like the docs allow but it seems to be impossible... Several other functions seem to not allow this capability.

Feature request toggle 'watching'

I've just implemented this in the python github client - this issue serves as a reminder to me, or anyone else who fancies a crack at it - to add this functionality to tentacat.

Subscribing to every public basho project on github

Link to PyGithub/PyGithub project page

Commit which added and tested this functionality.

Install the feature version :

pip install git+git://github.com/bryanhuntesl/PyGithub.git@esl-local-fix-watches        

Grab a github token, set it as an environmental variable and run this snippet:

from github import *
import os
g = Github(login_or_token=os.getenv("GITHUB_TOKEN"))
u=g.get_user()
org=g.get_organization("basho")
for r in org.get_repos():
    u.add_to_watched(r)

TADA

Now you're subscribed to every currently public basho repository on github

Next

Perform this same operation using tentacat.

Support for .diff and .patch mediatypes

GitHub API allows to set Accept header to application/vnd.github.v3.diff and application/vnd.github.v3.patch to return raw diffs and patches. This raises error in Tentacat because response body is always processed by JSX.decode!. Even if it is not json

Github rate limit

Currently theres no handling of the rate limit in this project. I regularly hit the rate limit (usually at the end of the hour) and would like to hear your thoughts on how to handle this properly.

Heres the exception I get when that happens:

[error] Task #PID<0.516.0> started from #PID<0.515.0> terminating
** (FunctionClauseError) no function clause matching in Tentacat.process_stream/1
    lib/tentacat.ex:102: Tentacat.process_stream({403, %{"documentation_url" => "https://developer.github.com/v3/#rate-limiting", "message" => "API rate limit exceeded for mgwidmann."}})
    (elixir) lib/stream.ex:1099: Stream.do_resource/5
    (elixir) lib/enum.ex:1486: Enum.reduce/3
    (elixir) lib/enum.ex:2248: Enum.to_list/1

Add headers for text match?

I'm trying to use Github's metadata matching to return code snippets/highlights in the response, as documented in https://developer.github.com/v3/search/#text-match-metadata. I know that I can add my own headers in HTTPoison, ie

header_list = Enum.to_list(headers)
    [{"Accept", "application/vnd.github.v3.text-match+json"} | header_list]

So I can get back something like this:

...
  "object_type": "FileContent",
  "property": "content",
  "fragment": "\",\n            \"key_limit\": 2,\n            \"owner\": {\n                \"email",
  "matches": [
    {
      "text": "key_limit",
      "indices": [
        16,
        25
      ]
	}
...

Is there a way to pass the header info during the client creation? I tried something like the following, but no luck:

Tentacat.Client.new(%{access_token: "#{token}", accept: "application/vnd.github.v3.text-match+json"}, "#{@uri}")

I also tried wrapping HTTPoison.base to pass the accept header, but I'm assuming that'll only work if I'm using all the HTTPoison base methods directly. Attempts to add text match as a header return results as a regular search api call. Any suggestions?

Add Issues.Events

I'd love to have access to the events within each issue.

Any reason not to add this as a feature?

Only able to retrieve first page of response

For API requests that have a large number of results, we're only returning the first page. Additionally because the headers are thrown away in the process_response call, we have no way to tell the user, "Hey, there are more pages to what you asked for."

Here's a link header from the call to Tentacat.Repositories.list_users("jeffweiss")

  {"X-GitHub-Media-Type", "github.v3; format=json"},
  {"Link",
   "<https://api.github.com/user/818053/repos?page=2>; rel=\"next\", <https://api.github.com/user/818053/repos?page=5>; rel=\"last\""},

support for Pulls.Reviews.create

Hi, I was searching for how to use the endpoint described here in Tentacat, but I wasn't able to find anything. Is is implemented yet?
(not related, the documentation can't be read online, it's dead link)

Idiomatic elixir would have the client as the first argument in api

One surprising thing about using tentacat is that the client argument is always the last item in function argument lists.

From the README, it would be better if we could do:

iex> Tentacat.Client.new |> Tentacat.Users.find "edgurgel", client

Instead of:

iex> client = Tentacat.Client.new
iex> Tentacat.Users.find "edgurgel", client

Update documentation to use client as first argument.

client = Tentacat.Client.new((%{access_token: "xxx"}))
Tentacat.Repositories.repo_get("elixir-conspiracy", "pacman", client)
** (Protocol.UndefinedError) protocol String.Chars not implemented for %Tentacat.Client...

Support to Github Http Redirects

When there is a 301 response from Github V3 Api an error is raised, in my understanding the redirect would have to be performed transparently.

The error I'm getting:

** (FunctionClauseError) no function clause matching in :lists.flatten/1
2017-09-06T15:20:05.510733+00:00 app[worker.1]:     (stdlib) lists.erl:616: :lists.flatten({301, %{"documentation_url" => "https://developer.github.com/v3/#http-redirects", "message" => "Moved Permanently", "url" => "https://api.github.com/repositories/28398133/pulls?state=open"}})

As you can see the "repos" was replaced by "repositories".

I'm running this code:

Tentacat.Pulls.filter(org, repo, %{state: "open"}, client)

See more:

https://developer.github.com/v3/#http-redirects

Argument error when running mix test

Following on from #57, I'm still having no luck trying to run tests ๐Ÿ˜ž.... I have 15 failures, all along the same line. Heres one:

 15) test remove/4 (Tentacat.Pulls.CommentsTest)
     test/pulls/comments_test.exs:56
     ** (ArgumentError) argument error
     stacktrace:
       (jsx) src/jsx_decoder.erl:234: :jsx_decoder.value/4
       (exjsx) lib/jsx.ex:15: JSX.decode!/2
       (tentacat) lib/tentacat.ex:13: Tentacat.process_response/1
       test/pulls/comments_test.exs:58
Finished in 7.5 seconds (0.5s on load, 6.9s on tests)
105 tests, 15 failures

While trying to solve this I have removed and reinstalled erlang via apt-get according to the Ubuntu instructions here: http://elixir-lang.org/install.html#unix-and-unix-like

justin@linisox:~/projects/tentacat$ elixir -v
Erlang/OTP 18 [erts-7.2] [source-e6dd627] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.2.0

The good news is that I have prototyped the search addition, it seems to work, so will write some tests and post the PR once this is resolved. ๐Ÿ˜„

Projects support

It will be really nice to have one library that helps to automate Github Projects workflow (eg list labels and set correct workflow status in GitHub Projects).

Tag + Release Tentacat 0.9

it looks like the release has been incremented in the repo (in light of the API change from #132) but it has not been tagged or released. can that be published to hex so we can use it? The standardized return type would be very helpful! thank you!

Client.new/0 is undefined

Brand new Elixir project, with just Tentacat as a dependency:

%  iex -S mix
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Tentacat.start
{:ok, [:idna, :hackney, :httpoison]}
iex(2)> client = Tentacat.Client.new
** (UndefinedFunctionError) undefined function: Tentacat.Client.new/0
    Tentacat.Client.new()
iex(2)>

Thoughts?

Error trying to record response with exvcr

Hi @edgurgel,

I am trying to write a test, which call to Tentacat.Repositories.list_mine(client) using exvcr, but I am getting an error:

stacktrace:
       (stdlib) gen.erl:168: :gen.do_call/4
       (elixir) lib/gen_server.ex:561: GenServer.call/3
       lib/exvcr/handler.ex:24: ExVCR.Handler.get_response_from_cache/2
       lib/exvcr/handler.ex:14: ExVCR.Handler.get_response/2
       src/meck_code_gen.erl:154: :meck_code_gen.exec/4
       (httpoison) lib/httpoison/base.ex:396: HTTPoison.Base.request/9
       (tentacat) lib/tentacat.ex:2: Tentacat.request!/5
       (tentacat) lib/tentacat.ex:110: Tentacat.request_with_pagination/4

As you use the same lib to record http responses, perhaps you know what's going on here.
Thanks!

per_page param in searches

Hi!
I'm trying to add the per_page param to the Tentacat.Search.users request but no options can be passed for that. Is there any other way of doing it?
I have seen this PR #106 which seems to add this, but it hasn't be merged. Are you planning to merge it?
Thanks in advance

Add search/issues endpoint

It looks like the rest of the Search API is supported but the search/issues endpoint isn't, it would be great to have that support :)

Undefined protocol?

Tentacat.Client.new (with & without credentials) works
Tentacat.Users.me(client) works

But more complicated functions like Tentacat.Users.find or Tentacat.Contents.find give me a "Protocol undefined error". Am I missing something?

untitled

is there a way to provide self-signed CA certificates?

I'm seeing this from Tentacat.Commits.find with a GHE using a self-signed CA:

19:02:06.119 [error] SSL: :certify: ssl_handshake.erl:1490:Fatal error: unknown ca

** (HTTPoison.Error) {:tls_alert, 'unknown ca'}
    (tentacat) lib/tentacat.ex:2: Tentacat.request!/5
    (tentacat) lib/tentacat.ex:42: Tentacat.json_request/5

I believe HTTPoison's request!/5 (which is used in Tentacat, e.g., here) takes some kind of list of options where I could specify a "cacertfile" path...

If not for #65 I'd try that, but is there an easier way to just override some HTTPoison default setting and provide a CA cert in my own project's config.exs?

Using codebase for other APIs

Hey @edgurgel! Good job with this wrapper for Github, I've been using it and it's really helpful. Is it ok to use this codebase to create other client APIs? What do you deem necessary, besides including your name on LICENSE? Thanks!

Move client to the be the first parameter

In both Elixir as in with Erlang the convention is that the client is the first parameter of a function.
You should consider doing this as I think it might look nicer especially when the client code is close to other client code that follows this standard practice.

First way to do this is to always a client instance for all calls. Even though the client is an empty/anonymous one.

This other was is that you could use the fact that default attributes can just as easily be the first one as the last. Thus changing:

    def find(user, client \\ %Client{}) do
      get "users/#{user}", client.auth
    end

into:

    def find(client \\ %Client{}, user) do
      get "users/#{user}", client.auth
    end

I know this is a pretty big breaking change. But I really think that code could end up looking nicer that way. ie.:

    client = %Tentacat.Client{auth: %{user: "user", password: "password"}}
    user = client |> Tentacat.Users.me
    client |> Tentacat.Organizations.list(user[:id])

on Windows, the repo cannot be cloned

C:\code\infr>git clone https://github.com/edgurgel/tentacat.git
Cloning into 'tentacat'...
remote: Counting objects: 1430, done.
rRemote: Total 1430 (delta 0), reused 0 (delta 0), pack-reused 1430eceiving objects:  94% (1345/1430), 164.01 KiR
Receiving objects: 100% (1430/1430), 286.35 KiB | 137.00 KiB/s, done.
Resolving deltas: 100% (797/797), done.
Checking connectivity... done.
fatal: cannot create directory at 'test/fixture/vcr_cassettes/followers#following?': Invalid argument
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry the checkout with 'git checkout -f HEAD'

This seems to be due to illegal characters in paths, particularly ?.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx

Tentacat has a bunch of those here:
https://github.com/edgurgel/tentacat/tree/master/test/fixture/vcr_cassettes

๐Ÿ˜…

GitHub response pagination

How is pagination handled by Tentacat ?

I didn't find any mention of it in the documentation. These tests gave me some insight but I would like a more thorough answer :)

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.