NotionのAPIをつかってNotionとGitHubを連携する

2021/07/18に公開

NotionのAPIを使ってGitHub issueをつくってみました。

モチベーション

Notionは公式ではGitHubと連携する機能がありません。
そのため、ソフトウェア開発をNotionでタスク管理するのにちょっと難があります。
サードパーティのサービスを使えばできるらしいですが、せっかく最近Public BetaのAPIが出たのでそれを応用すればサクッとできるんじゃないかと思ってやってみました。

Notion APIについて

https://developers.notion.com/

公式のSDK

https://github.com/makenotion/notion-sdk-js/
js用のSDKです。TypeScriptの型定義もあります。

この記事でやること

  1. Notionのデータベースからページ一覧を取得する
  2. ページごとにGitHubのissueをつくって相互リンクを貼る

この記事でやらないこと

  • GitHub IssueからNotionへの書き込み
    • (あくまでも情報はNotion側に集約されている前提)
  • GitHub Issueをつくった後の情報の同期
    • タイトルやステータスの同期

成果物

https://github.com/YusukeKokubo/create-github-issues-by-notion-database

Notionのデータベースからページ一覧を取得する

.envから読み込む定数

const notion = new Client({ auth: process.env["NOTION_KEY"] })
const DATABASE_ID = process.env["NOTION_DATABASE_ID"]
const PROPERTY_TITLE = process.env["PROPERTY_TITLE"]
const PROPERTY_NO = process.env["PROPERTY_NO"]
const PROPERTY_GITHUB = process.env["PROPERTY_GITHUB"]

NOTION_KEYは https://developers.notion.com/docs/getting-started を元に作成するトークンです。
DATABASE_IDは取得したいデータベースのidです。URLからコピペするのが簡単。

PROPERTY_TITLEはタイトルプロパティのプロパティ名
PROPERTY_NOはGitHub issueの番号を入れるプロパティのプロパティ名
PROPERTY_GITHUBはGitHub Issueへのリンクを入れる用のプロパティのプロパティ名

Notion APIでカーソルを使いながら全件を取得する

import { Client } from "@notionhq/client"
import { InputPropertyValueMap } from "@notionhq/client/build/src/api-endpoints"
import { TitlePropertyValue } from "@notionhq/client/build/src/api-types"

async function getTasksFromDatabase() {
  const tasks: Page[] = []
  async function getPageOfTasks(cursor: string | null) {
    const current_pages = await notion.databases.query({
      database_id: DATABASE_ID,
      filter: {
        property: PROPERTY_NO,
        number: {
          is_empty: true
        },
      },
      start_cursor: cursor
    })
    console.log('pages count: ', current_pages.results.length)

    for (const page of current_pages.results) {
      if (page.object === 'page') {
        if (page.properties[PROPERTY_TITLE] && (page.properties[PROPERTY_TITLE] as TitlePropertyValue).title[0]) {
          tasks.push({
            id: page.id,
            title: (page.properties[PROPERTY_TITLE] as TitlePropertyValue).title[0].plain_text,
            url: page.url,
          })
        }
      }
    }
    if (current_pages.has_more) {
      await getPageOfTasks(current_pages.next_cursor)
    }
  }
  await getPageOfTasks(undefined)
  return tasks
}

ちゃんとエラー制御をできてないですが、こんな感じでいけます。カーソルを使う必要がなければもっとシンプルに書けます。

GitHubにissueをつくって相互リンクを貼る

GitHubのSDKは公式のoctokitを使います。

async function createGitHubIssues(tasks: Page[]) {
  for (const [index, task] of Object.entries(tasks)) {
    const createdIssue = await octokit.rest.issues.create({
      owner: process.env["REPO_GITHUB_OWNER"],
      repo: process.env["REPO_GITHUB_REPO"],
      title: task.title,
      body: task.url
    })

    const propertyValues: InputPropertyValueMap = {}
    propertyValues[PROPERTY_NO] = {
      type: 'number',
      number: createdIssue.data.number
    }
    propertyValues[PROPERTY_GITHUB] = {
      type: 'url',
      url: createdIssue.data.html_url
    }

    notion.pages.update({ page_id: task.id, properties: propertyValues, archived: false })
    console.log('created', task.title, createdIssue.data.number)

    // TODO: github apiのrate limitを回避するためにsleepした方がよい
  }
}

octokit.rest.issues.create した後のレスポンスからissue番号、issueのURLを取得して、 notion.pages.update してます。

こんな感じでNotionからGitHub issueをつくって、相互リンクを貼ることができました。

まとめ

これでNotionのタスクと、GitHubをリンクさせることができました。
NotionとPRもissueを経由することで関連リンクをたどることができます。

コード全文はこちらをどうぞ。
https://github.com/YusukeKokubo/create-github-issues-by-notion-database

この記事で触れてない作成後のタイトルとステータスの同期も実装してます。

Discussion