LoginSignup
6
3

More than 3 years have passed since last update.

GitHub REST API から Node.js で 特定の organization の issue の一覧を取得する

Posted at

コード

古い issue の一覧をチャットに通知するツールを作成しておりまして、その一環として書いたコードです。
組織(ユーザー)名、リポジトリ名はクエリパラメータに設定するなど複数パターンがあるようですが、今回は下記URLでアクセスしました。

  • [GET] https://api.github.com/orgs/{org}/issues

コードは下記の通りです。

import fetch from 'isomorphic-unfetch';
import { Issue, State } from './types/vendor';

export async function get_issues(
  owner: string,
  repository: string,
  api_token: string,
  state: State  // `State`の方は`'open' | 'closed' | 'all'`です。
): Promise<Issue[]> {
  const response = await fetch(
    `https://api.github.com/repos/${owner}/${repository}/issues` +
      `?state=${state}`,
    {
      headers: {
        Authorization: `token ${api_token}`,
        Accept: 'application/vnd.github.v3+json',
      },
    }
  );
  if (response.status != 200) {
    throw new Error(
      `GitHub API にアクセスできませんでした: ${JSON.stringify(
        await response.json(),
        null,
        '  '
      )}`
    );
  }
  return (await response.json()) as Issue[];
}

Node.js 環境でも ブラウザ環境でも動くfetchを使用するためにisomorphic-unfetchを使用しています。

# yarn の場合
$ yarn add isomorphic-unfetch

# npm の場合
$ npm install isomorphic-unfetch

Issueの型は QuickType でinterface自動生成してtypeに差し替えました。
型の詳しい内容は下記の実際のソースをご確認ください。
https://github.com/sugu-sano/notify-old-issues/blob/master/src/types/vendor/isssue.ts

今回は不要でしたので設定しませんでしたが、クエリパラメータにはsort(並び順)、since(指定された時間以降に更新された)もありました。詳しくは下記公式ドキュメントを参照ください。

List repository issues - GitHub Docs
https://docs.github.com/en/free-pro-team@latest/rest/reference/issues#list-repository-issues

Octkit という GitHub 公式の REST クライアントが存在した

生のfetch APIでアクセスしていましたが GitHub にはOctokitという公式クライアントがありました。
また型定義も提供されていてパラメータやレスポンスの型は自作しなくてもタイプセーフに扱うことができます。

# yarn の場合
$ yarn add @octokit/core @octokit/types

# npm の場合
$ npm install @octokit/core @octokit/types
import { Octokit } from "@octokit/core";
import { Endpoints } from "@octokit/types";

async function main() {
  // 型の取得の仕方に若干クセがある
  type route = "GET /repos/:owner/:repo/issues";
  type Response = Endpoints[route]["response"];
  type Parameters = Endpoints[route]["parameters"];

  const params: Parameters = {
    owner: "octocat",
    repo: "hello-world",
    since: "2020-11-20T00:00:00",
  };

  const octokit = new Octokit();
  // 戻り値が `OctokitResponse<any>` にならないように型注釈
  const response: Response = await octokit.request(
    "GET /repos/{owner}/{repo}/issues",
    params
  );

  console.log(response.data);  // `any` でなく `IssuesListForRepoResponseData` 型になる
}
main();

実行すると下記レスポンスが確認できました。

レスポンス(長いので折りたたみ)
[
  {
    url: 'https://api.github.com/repos/octocat/Hello-World/issues/812',
    repository_url: 'https://api.github.com/repos/octocat/Hello-World',
    labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/labels{/name}',
    comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/comments',
    events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/events',
    html_url: 'https://github.com/octocat/Hello-World/issues/812',
    id: 748885338,
    node_id: 'MDU6SXNzdWU3NDg4ODUzMzg=',
    number: 812,
    title: 'Test title',
    user: {
      login: 'avihlbi',
      id: 54238151,
      node_id: 'MDQ6VXNlcjU0MjM4MTUx',
      avatar_url: 'https://avatars0.githubusercontent.com/u/54238151?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/avihlbi',
      html_url: 'https://github.com/avihlbi',
      followers_url: 'https://api.github.com/users/avihlbi/followers',
      following_url: 'https://api.github.com/users/avihlbi/following{/other_user}',
      gists_url: 'https://api.github.com/users/avihlbi/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/avihlbi/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/avihlbi/subscriptions',
      organizations_url: 'https://api.github.com/users/avihlbi/orgs',
      repos_url: 'https://api.github.com/users/avihlbi/repos',
      events_url: 'https://api.github.com/users/avihlbi/events{/privacy}',
      received_events_url: 'https://api.github.com/users/avihlbi/received_events',
      type: 'User',
      site_admin: false
    },
    labels: [],
    state: 'open',
    locked: false,
    assignee: null,
    assignees: [],
    milestone: null,
    comments: 1,
    created_at: '2020-11-23T15:13:32Z',
    updated_at: '2020-11-23T15:13:33Z',
    closed_at: null,
    author_association: 'NONE',
    active_lock_reason: null,
    body: 'Test description',
    performed_via_github_app: null
  },
  {
    url: 'https://api.github.com/repos/octocat/Hello-World/issues/810',
    repository_url: 'https://api.github.com/repos/octocat/Hello-World',
    labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/labels{/name}',
    comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/comments',
    events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/events',
    html_url: 'https://github.com/octocat/Hello-World/pull/810',
    id: 747843269,
    node_id: 'MDExOlB1bGxSZXF1ZXN0NTI0OTkzMTY0',
    number: 810,
    title: 'Test PR for Codespaces',
    user: {
      login: '2percentsilk',
      id: 3174849,
      node_id: 'MDQ6VXNlcjMxNzQ4NDk=',
      avatar_url: 'https://avatars3.githubusercontent.com/u/3174849?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/2percentsilk',
      html_url: 'https://github.com/2percentsilk',
      followers_url: 'https://api.github.com/users/2percentsilk/followers',
      following_url: 'https://api.github.com/users/2percentsilk/following{/other_user}',
      gists_url: 'https://api.github.com/users/2percentsilk/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/2percentsilk/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/2percentsilk/subscriptions',
      organizations_url: 'https://api.github.com/users/2percentsilk/orgs',
      repos_url: 'https://api.github.com/users/2percentsilk/repos',
      events_url: 'https://api.github.com/users/2percentsilk/events{/privacy}',
      received_events_url: 'https://api.github.com/users/2percentsilk/received_events',
      type: 'User',
      site_admin: false
    },
    labels: [],
    state: 'open',
    locked: false,
    assignee: null,
    assignees: [],
    milestone: null,
    comments: 0,
    created_at: '2020-11-20T22:48:47Z',
    updated_at: '2020-11-20T22:48:47Z',
    closed_at: null,
    author_association: 'NONE',
    active_lock_reason: null,
    pull_request: {
      url: 'https://api.github.com/repos/octocat/Hello-World/pulls/810',
      html_url: 'https://github.com/octocat/Hello-World/pull/810',
      diff_url: 'https://github.com/octocat/Hello-World/pull/810.diff',
      patch_url: 'https://github.com/octocat/Hello-World/pull/810.patch'
    },
    body: '',
    performed_via_github_app: null
  },
  {
    url: 'https://api.github.com/repos/octocat/Hello-World/issues/808',
    repository_url: 'https://api.github.com/repos/octocat/Hello-World',
    labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/labels{/name}',
    comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/comments',
    events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/events',
    html_url: 'https://github.com/octocat/Hello-World/issues/808',
    id: 744550518,
    node_id: 'MDU6SXNzdWU3NDQ1NTA1MTg=',
    number: 808,
    title: 'Click Here',
    user: {
      login: 'irfaardy',
      id: 49023326,
      node_id: 'MDQ6VXNlcjQ5MDIzMzI2',
      avatar_url: 'https://avatars1.githubusercontent.com/u/49023326?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/irfaardy',
      html_url: 'https://github.com/irfaardy',
      followers_url: 'https://api.github.com/users/irfaardy/followers',
      following_url: 'https://api.github.com/users/irfaardy/following{/other_user}',
      gists_url: 'https://api.github.com/users/irfaardy/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/irfaardy/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/irfaardy/subscriptions',
      organizations_url: 'https://api.github.com/users/irfaardy/orgs',
      repos_url: 'https://api.github.com/users/irfaardy/repos',
      events_url: 'https://api.github.com/users/irfaardy/events{/privacy}',
      received_events_url: 'https://api.github.com/users/irfaardy/received_events',
      type: 'User',
      site_admin: false
    },
    labels: [],
    state: 'open',
    locked: false,
    assignee: null,
    assignees: [],
    milestone: null,
    comments: 1,
    created_at: '2020-11-17T09:09:54Z',
    updated_at: '2020-11-23T09:43:57Z',
    closed_at: null,
    author_association: 'NONE',
    active_lock_reason: null,
    body: 'I love you\r\n\r\n----\r\n[Click Here](https://github.com/irfaardy)',
    performed_via_github_app: null
  },
  {
    url: 'https://api.github.com/repos/octocat/Hello-World/issues/576',
    repository_url: 'https://api.github.com/repos/octocat/Hello-World',
    labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/labels{/name}',
    comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/comments',
    events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/events',
    html_url: 'https://github.com/octocat/Hello-World/pull/576',
    id: 515476262,
    node_id: 'MDExOlB1bGxSZXF1ZXN0MzM0OTMzMjIy',
    number: 576,
    title: 'Update README',
    user: {
      login: 'NX007KTR',
      id: 41190306,
      node_id: 'MDQ6VXNlcjQxMTkwMzA2',
      avatar_url: 'https://avatars3.githubusercontent.com/u/41190306?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/NX007KTR',
      html_url: 'https://github.com/NX007KTR',
      followers_url: 'https://api.github.com/users/NX007KTR/followers',
      following_url: 'https://api.github.com/users/NX007KTR/following{/other_user}',
      gists_url: 'https://api.github.com/users/NX007KTR/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/NX007KTR/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/NX007KTR/subscriptions',
      organizations_url: 'https://api.github.com/users/NX007KTR/orgs',
      repos_url: 'https://api.github.com/users/NX007KTR/repos',
      events_url: 'https://api.github.com/users/NX007KTR/events{/privacy}',
      received_events_url: 'https://api.github.com/users/NX007KTR/received_events',
      type: 'User',
      site_admin: false
    },
    labels: [],
    state: 'open',
    locked: false,
    assignee: null,
    assignees: [],
    milestone: null,
    comments: 1,
    created_at: '2019-10-31T14:26:43Z',
    updated_at: '2020-11-29T05:03:18Z',
    closed_at: null,
    author_association: 'NONE',
    active_lock_reason: null,
    pull_request: {
      url: 'https://api.github.com/repos/octocat/Hello-World/pulls/576',
      html_url: 'https://github.com/octocat/Hello-World/pull/576',
      diff_url: 'https://github.com/octocat/Hello-World/pull/576.diff',
      patch_url: 'https://github.com/octocat/Hello-World/pull/576.patch'
    },
    body: '',
    performed_via_github_app: null
  }
]

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3