{"id":31285715,"url":"https://github.com/eamonnsullivan/github-api-lib","last_synced_at":"2025-09-24T08:14:03.434Z","repository":{"id":46681001,"uuid":"306126046","full_name":"eamonnsullivan/github-api-lib","owner":"eamonnsullivan","description":"The bits of the Github GraphQL and REST API that I need for various projects, kept in one place.","archived":false,"fork":false,"pushed_at":"2021-09-30T12:17:46.000Z","size":65,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-06T22:18:50.077Z","etag":null,"topics":["clojars","clojure","github-graphql"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eamonnsullivan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-21T19:24:11.000Z","updated_at":"2021-09-30T12:15:26.000Z","dependencies_parsed_at":"2022-08-26T09:21:28.017Z","dependency_job_id":null,"html_url":"https://github.com/eamonnsullivan/github-api-lib","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/eamonnsullivan/github-api-lib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eamonnsullivan%2Fgithub-api-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eamonnsullivan%2Fgithub-api-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eamonnsullivan%2Fgithub-api-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eamonnsullivan%2Fgithub-api-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eamonnsullivan","download_url":"https://codeload.github.com/eamonnsullivan/github-api-lib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eamonnsullivan%2Fgithub-api-lib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276714457,"owners_count":25691398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-24T02:00:09.776Z","response_time":97,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojars","clojure","github-graphql"],"created_at":"2025-09-24T08:14:02.180Z","updated_at":"2025-09-24T08:14:03.427Z","avatar_url":"https://github.com/eamonnsullivan.png","language":"Clojure","readme":"# github-api-lib\n\nA small, very simple library with bits and pieces of Github's GraphQL and REST API, in one place for my own convenience.\n\n[![CircleCI](https://circleci.com/gh/eamonnsullivan/github-api-lib.svg?style=shield)](https://circleci.com/gh/eamonnsullivan/github-api-lib/tree/main) [![Clojars Project](https://img.shields.io/clojars/v/eamonnsullivan/github-api-lib.svg)](https://clojars.org/eamonnsullivan/github-api-lib)\n\n## Usage\n\nYou will need a Github access token with `repo` permissions. This is one way to provide that value:\n```clojure\n(def token (System/getenv \"GITHUB_ACCESS_TOKEN\"))\n```\n### Core functions\n```clojure\n(require '[eamonnsullivan.github-api-lib.core :as core])\n\n;; make your own graphql query\n(def get-repo-id\n   \"query getRepoId ($owner: String!, $name: String!) {\n      repository(owner:$owner, name:$name) {\n        id\n      }\n    }\n   \")\n\n(core/make-graphql-post\n   token\n   get-repo-id\n   {:owner \"eamonnsullivan\" :name \"github-api-lib\"})\n```\n### Repositories\n```clojure\n(require '[eamonnsullivan.github-api-lib.repos :as repos])\n\n(repos/get-repo-id token \"https://github.com/eamonnsullivan/github-api-lib\")\n;; \"MDEwOlJlcG9zaXRvcnkzMDYxMjYwNDY=\"\n\n(repos/get-repo-topics token \"eamonnsullivan/github-api-lib\")\n;; [\"clojure\" \"clojars\" \"github-graphql\"]\n\n```\n### Pull Requests\n\n```clojure\n(require '[eamonnsullivan.github-api-lib.pull-requests :as pr])\n```\n\nAll of these methods return a map of information about the new or updated pull request or comment, such as the `:body` (in markdown), `:title`, `:permalink` or whether the pull request `:isDraft` or `:mergeable`.\n\n#### Create a new pull request\n```clojure\n(def options {:title \"A title for the pull request\"\n              :body \"The body of the pull request\"\n              :base \"main or master, usually\"\n              :branch \"the name of the branch you want to merge\"\n              :draft true})\n(def new-pr-url (:permalink (pr/create-pull-request\n                 token\n                 \"https://github.com/eamonnsullivan/github-pr-lib\" options)))\n```\nThe `:title`, `:base` and `:branch` are mandatory. You can omit the `:body`, and `:draft` defaults to true.\n\n#### Update a pull request\n```clojure\n(def updated {:title \"A new title\"\n              :body \"A new body\"})\n(pr/update-pull-request token new-pr-url updated)\n```\n#### Mark a pull request as ready for review\n```clojure\n(pr/mark-ready-for-review token new-pr-url)\n```\n#### Comment on a pull request\nOnly handles issue comments on pull requests at the moment. The body text can use Github-style markdown.\n```clojure\n;; returns the permalink for the comment\n(def comment-link (pr/add-pull-request-comment token new-pr-url \"Another comment.\"))\n```\n#### Edit an issue comment\n```clojure\n(pr/edit-pull-request-comment token comment-link\n                           \"The new body for the comment, with *some markdown* and `stuff`.\")\n```\n#### Close a pull request\n```clojure\n(pr/close-pull-request token new-pr-url)\n```\n#### Reopen a pull request\n```clojure\n(pr/reopen-pull-request token new-pr-url)\n```\n#### Merge a pull request\n```clojure\n;; All of these fields are optional. The merge-method will default to \"SQUASH\".\n;; The merge will fail if the pull-request's URL can't be found, if the pull\n;; request's head reference is out-of-date or if there are conflicts.\n(def merge-options {:title \"A title or headline for the commit.\"\n                    :body \"The commit message body.\"\n                    :mergeMethod \"MERGE\" or \"REBASE\" or \"SQUASH\"\n                    :authorEmail \"someone@somwhere.com\"})\n(pr/merge-pull-request token new-pr-url merge-options)\n```\n#### Misc. info\n```clojure\n;; Various bits of information, such as whether it is mergeable or a draft.\n(pr/get-pull-request-info token new-pr-url)\n```\n\n### Searching for topics\n\n```clojure\n(require '[eamonnsullivan.github-api-lib.repo-search :as rs])\n(def result (rs/get-repos token \"my-org\" [\"topic1\" \"topic2\"]))\n(spit \"repos.edn\" result)\n```\nThe EDN returned will contain basic information about the repos found. For example:\n\n```edn\n[{:name \"project1\",\n  :description\n  \"A description\",\n  :url \"https://github.com/my-org/project1\",\n  :sshUrl \"git@github.com:my-org/project1.git\",\n  :updatedAt \"2020-04-09T11:01:55Z\",\n  :languages [\"Javascript\" \"Python\" \"HTML\"]}\n {:name \"project2\",\n  :description \"A description for project2\",\n  :url \"https://github.com/my-org/project2\",\n  :sshUrl \"git@github.com:my-org/project2.git\",\n  :updatedAt \"2020-04-09T11:02:28Z\",\n  :languages [\"Clojure\" \"ClojureScript\"]}\n]\n```\n\n### Getting files in repos\n\nRetrieve information about a file in a repository, on a particular branch. You can use \"HEAD\" for the branch to retrieve a file from the default branch. The information returns includes `:byteSize` and `:text`.\n\n```clojure\n(require '[eamonnsullivan.github-api-lib.files :as files])\n(files/get-file token \"eamonnsullivan\" \"github-api-lib\" \"HEAD\" \"README.md\")\n\n{:commitResourcePath\n \"/eamonnsullivan/github-api-lib/commit/0805f4b95f5e01275e5962e0f8ed23def5129419\",\n :byteSize 4296,\n :filepath \"README.md\",\n :abbreviatedOid \"0805f4b\",\n :isBinary false,\n :oid \"0805f4b95f5e01275e5962e0f8ed23def5129419\",\n :commitUrl\n \"https://github.com/eamonnsullivan/github-api-lib/commit/...\",\n :isTruncated false,\n :text\n \"# github-api-lib\\n\\nA small, very simple...\"}\n```\n\nYou can also try several files and the first one found is returned.\n```clojure\n(files/get-first-file token \"eamonnsullivan\" \"github-api-lib\" \"HEAD\"\n[\"build.sbt\" \".nvmrc\" \"deps.edn\" \"project.edn\"])\n\n{:commitResourcePath\n \"/eamonnsullivan/github-api-lib/commit/74c3092ef552681a7fa5c1a96b3a11479b4f0a28\",\n :byteSize 1257,\n :filepath \"deps.edn\",\n :abbreviatedOid \"74c3092\",\n :isBinary false,\n :oid \"74c3092ef552681a7fa5c1a96b3a11479b4f0a28\",\n :commitUrl\n \"https://github.com/eamonnsullivan/github-api-lib/commit/...\",\n :isTruncated false,\n :text\n \"{:paths [\\\"src\\\" \\\"resources\\\"]\\n :deps ...\"}\n```\n\n### Handling paged responses\n\nThe library has a helper function to retrieve all of the pages of a search as a flattened, realised sequence.\n\nSee the doc string for more details, but it is normally called with:\n * a function to retrieve one of the pages\n * a predicate that returns truthy if there are results on that page\n * a function to extract the values you want from each page\n * A function to retrieve the cursor for the next page.\n\nIt obviously would be a poor choice for a very large result set, but it can be convenient for a known limited set. In this example, the function is used to get all of the topics on a given repository.\n\n```clojure\n(require '[eamonnsullivan.github-api-lib.core :as core]\n         '[eamonnsullivan.github-api-lib.repos :as repos])\n\n(defn get-all-topics [token repo-url page-size]\n        (let [id (repos/get-repo-id token repo-url)\n              get-page (partial repos/get-page-of-topics token id page-size)\n              results? (fn [page] (some? (repos/get-topics page)))\n              get-next (fn [ret] (if (-\u003e ret :data :node :repsitoryTopics :pageInfo :hasNextPage)\n                                   (-\u003e ret :data :node :repositoryTopics :pageInfo :endCursor)\n                                   nil))]\n          (core/get-all-pages get-page results? repos/get-topics get-next)))\n\n(get-all-topics token \"https://github.com/eamonnsullivan/github-api-lib\" 10)\n;; [\"clojure\" \"clojars\" \"github-graphql\"]\n\n```\n## Development Notes\n\nTo run the project's tests:\n\n    $ clojure -M:test:runner\n\nTo check test coverage:\n\n    $ clojure -M:test:coverage\n\nTo build a deployable jar of this library:\n\n    $ clojure -Spom               # to update any dependencies\n    $ clojure -M:jar\n\nTo install the library locally:\n\n    $ clojure -M:install\n\nTo deploy it to Clojars -- needs `CLOJARS_USERNAME` and `CLOJARS_PASSWORD` environment variables or Maven settings:\n\n    $ clojure --M:deploy\n\n## License\n\nCopyright © 2020 Eamonn Sullivan\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feamonnsullivan%2Fgithub-api-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feamonnsullivan%2Fgithub-api-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feamonnsullivan%2Fgithub-api-lib/lists"}