Accessing repository dependencies in the GitHub GraphQL API

Access to a Repositories Dependency Graph describes a preview API for accessing GitHub repository dependencies.

To access the preview you need to send this Accept: header: application/vnd.github.hawkgirl-preview+json

But... GitHub's own GraphQL explorer at https://developer.github.com/v4/explorer/ doesn't currently allow you to set custom HTTP headers.

Installing GraphiQL

So I decided to try https://github.com/skevy/graphiql-app - since it's mentioned in the GitHub docs here.

brew cask install graphiql

Then you can launch the app from /Applications/GraphiQL.app.

I created a personal access token at https://github.com/settings/tokens called graphiql and gave it all of the read: permissions.

I launched the graphiql app and added the following headers:

Authorization: Bearer MY-PERSONAl-ACCESS-TOKEN
Accept: application/vnd.github.hawkgirl-preview+json

I added https://api.github.com/graphql as the endpoint.

I tested it by running these queries:

{
  user(login:"simonw") {
    id
    name
    url
    websiteUrl
  }
}
{
  repository(owner:"simonw", name:"datasette") {
    id
    name
    issues {
      totalCount
    }
  }
}
{
  search(type:REPOSITORY query:"datasette" first:10) {
    repositoryCount
    edges {
      node {
        __typename
        ... on Repository {
          nameWithOwner
          description
        }
      }
    }
  }
}

Then I figured out this query (using autocomplete) which returns dependencies detected for a repo:

{
  repository(owner:"simonw", name:"datasette") {
    dependencyGraphManifests {
      totalCount
      nodes {
        filename
      }
      edges {
        node {
          blobPath
          dependencies {
            totalCount
            nodes {
              packageName
              requirements
              hasDependencies
              packageManager
            }
          }
        }
      }
    }
  }
}

This gave me back:

{
  "data": {
    "repository": {
      "dependencyGraphManifests": {
        "totalCount": 1,
        "nodes": [
          {
            "filename": "setup.py"
          }
        ],
        "edges": [
          {
            "node": {
              "blobPath": "/simonw/datasette/blob/master/setup.py",
              "dependencies": {
                "totalCount": 12,
                "nodes": [
                  {
                    "packageName": "aiofiles",
                    "requirements": "~> 0.4.0",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "click",
                    "requirements": "~> 7.1.1",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "click-default-group",
                    "requirements": "~> 1.2.2",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "datasette",
                    "requirements": "",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "hupper",
                    "requirements": "~> 1.9",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "janus",
                    "requirements": "~> 0.4.0",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "jinja2",
                    "requirements": "~> 2.10.3",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "mergedeep",
                    "requirements": "~> 1.1.1",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "pint",
                    "requirements": "~> 0.9",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "pluggy",
                    "requirements": "~> 0.13.0",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "pyyaml",
                    "requirements": "~> 5.3",
                    "hasDependencies": false,
                    "packageManager": "PIP"
                  },
                  {
                    "packageName": "uvicorn",
                    "requirements": "~> 0.11",
                    "hasDependencies": true,
                    "packageManager": "PIP"
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}

Sadly I really wanted to get the dependents, not the dependencies - but that's still not available even as a preview API. So I scraped them instead.

Created 2020-04-30T14:46:40-07:00, updated 2020-04-30T16:18:03-07:00 · History · Edit