GraphQL query to get file info from GitHub repository

I would like to use GitHub repository for posts in my Gatsby site. Right now I'm using two queries, first to get the names of the files:

{
  viewer {
    repository(name: "repository-name") {
      object(expression: "master:") {
        id
        ... on Tree {
          entries {
            name
          }
        }
      }
      pushedAt
    }
  }
}

And the second to get the contents of the files:

{
  viewer {
    repository(name: "repository-name") {
      object(expression: "master:file.md") {
        ... on Blob {
          text
        }
      }
    }
  }
}

Is there any way to get information about when each file was created and last updated with GraphQL? Right now I can get only pushedAt for the whole repository and not individual files.

1 ответ

Решение

Вы можете использовать следующий запрос, чтобы получить содержимое файла и одновременно получить последнюю фиксацию для этого файла. Таким образом, вы также получите поляpushedAt, committedDate а также authorDate в зависимости от того, что вам нужно:

{
  repository(owner: "torvalds", name: "linux") {
    content: object(expression: "master:Makefile") {
      ... on Blob {
        text
      }
    }
    info: ref(qualifiedName: "master") {
      target {
        ... on Commit {
          history(first: 1, path: "Makefile") {
            nodes {
              author {
                email
              }
              message
              pushedDate
              committedDate
              authoredDate
            }
            pageInfo {
              endCursor
            }
            totalCount
          }
        }
      }
    }
  }
}

Обратите внимание, что нам также нужно получить endCursor поле, чтобы получить первую фиксацию файла (чтобы получить дату создания файла)

Например, в репозитории Linux дляMakefile файл дает:

"pageInfo": {
  "endCursor": "b29482fde649c72441d5478a4ea2c52c56d97a5e 0"
}
"totalCount": 1806

Итак, для этого файла есть фиксация 1806

Чтобы получить первую фиксацию, запрос, ссылающийся на последний курсор, который будет b29482fde649c72441d5478a4ea2c52c56d97a5e 1804:

{
  repository(owner: "torvalds", name: "linux") {
    info: ref(qualifiedName: "master") {
      target {
        ... on Commit {
          history(first: 1, after:"b29482fde649c72441d5478a4ea2c52c56d97a5e 1804", path: "Makefile") {
            nodes {
              author {
                email
              }
              message
              pushedDate
              committedDate
              authoredDate
            }
          }
        }
      }
    }
  }
}

который возвращает первую фиксацию этого файла.

У меня нет источника о формате строки курсора "b29482fde649c72441d5478a4ea2c52c56d97a5e 1804", Я тестировал некоторые другие репозитории с файлами с более чем 1000 коммитов, и кажется, что он всегда форматируется следующим образом:

<static hash> <incremented_number>

которые избегают перебора всех коммитов в случае, если есть более 100 коммитов, ссылающихся на ваш файл

Вот реализация на javascript с использованием graphql.js:

const graphql = require('graphql.js');

const token = "YOUR_TOKEN";
const queryVars = { name: "linux", owner: "torvalds" };
const file = "Makefile";
const branch = "master";

var graph = graphql("https://api.github.com/graphql", {
  headers: {
    "Authorization": `Bearer ${token}`,
    'User-Agent': 'My Application'
  },
  asJSON: true
});

graph(`
    query ($name: String!, $owner: String!){
      repository(owner: $owner, name: $name) {
        content: object(expression: "${branch}:${file}") {
          ... on Blob {
            text
          }
        }
        info: ref(qualifiedName: "${branch}") {
          target {
            ... on Commit {
              history(first: 1, path: "${file}") {
                nodes {
                  author {
                    email
                  }
                  message
                  pushedDate
                  committedDate
                  authoredDate
                }
                pageInfo {
                  endCursor
                }
                totalCount
              }
            }
          }
        }
      }
    }
`)(queryVars).then(function(response) {
  console.log(JSON.stringify(response, null, 2));
  var totalCount = response.repository.info.target.history.totalCount;
  if (totalCount > 1) {
    var cursorPrefix = response.repository.info.target.history.pageInfo.endCursor.split(" ")[0];
    var nextCursor = `${cursorPrefix} ${totalCount-2}`;
    console.log(`total count : ${totalCount}`);
    console.log(`cursorPrefix : ${cursorPrefix}`);
    console.log(`get element after cursor : ${nextCursor}`);

    graph(`
      query ($name: String!, $owner: String!){
        repository(owner: $owner, name: $name) {
          info: ref(qualifiedName: "${branch}") {
            target {
              ... on Commit {
                history(first: 1, after:"${nextCursor}", path: "${file}") {
                  nodes {
                    author {
                      email
                    }
                    message
                    pushedDate
                    committedDate
                    authoredDate
                  }
                }
              }
            }
          }
        }
      }`)(queryVars).then(function(response) {
        console.log("first commit info");
        console.log(JSON.stringify(response, null, 2));
      }).catch(function(error) {
        console.log(error);
      });
  }
}).catch(function(error) {
  console.log(error);
});
Другие вопросы по тегам