Open10

Notion AI でコミットメッセージを生成する実験

hankei6kmhankei6km

以前にも少し書いたように、AI が diff からコミットメッセージを生成してくれるとうれしい。

しばらく Notion AI を使ってみて、「わりといけそうかな」という気もしてきたので試してみた。

hankei6kmhankei6km

準備

他の AI チャットなどは使ったことがないので「そういうもの」なのかは不明だけど、Notion AI では「AI に依頼」を実行すると前後のテキストなどに影響されるように見える。

よって、最初に下記のようなメモを作成する。


diff からコミットメッセージを生成する

現在は手動でコミットメッセージを入力している

そのときは、下記のような情報も付与している。

Conventional Commits

https://www.conventionalcommits.org/ja/v1.0.0/

コミットメッセージのテンプレート

type: Subject

# feat: (new feature for the user, not a new feature for build script)
# fix: (bug fix for the user, not a fix to a build script)
# deps: dependencies
# docs: (changes to the documentation)
# style: (formatting, missing semi colons, etc; no production code change)
# refactor: (refactoring production code, eg. renaming a variable)
# test: (adding missing tests, refactoring tests; no production code change)
# chore: (updating grunt tasks etc; no production code change)
# 
# ## minor change
# 
# Format: `<type>(<scope>): <subject>`
# 
# `<scope>` is optional
#
# ## major(breaking) change
# 
# Format: `<type>(<scope>)!: <subject>`
# 
# `<scope>` is optional
# 
# ## Example
# 
# ```
# feat: add hat wobble
# ^--^  ^------------^
# |     |
# |     +-> Summary in present tense.
# |
# +-------> Type: chore, docs, feat, fix, refactor, style, or test.
# ```
# 
# ## References:
# 
# - https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716
# - https://zenn.dev/uochan/articles/2021-12-08-vim-conventional-commits
# - https://www.conventionalcommits.org/ja/v1.0.0/
# - https://www.conventionalcommits.org/
# - https://seesparkbox.com/foundry/semantic_commit_messages
# - http://karma-runner.github.io/1.0/dev/git-commit-msg.html

# ==== The Seven Rules ====
# 1. Separate subject from body with a blank line
# 2. Limit the subject line to 50 characters
# 3. Capitalize the subject line
# 4. Do not end the subject line with a period
# 5. Use the imperative mood in the subject line
# 6. Wrap the body at 72 characters
# 7. Use the body to explain what and why vs. how
#
# How to Write a Git Commit Message http://chris.beams.io/posts/git-commit/

# for http://memo.goodpatch.co/2016/07/beautiful-commits-with-emojis/
hankei6kmhankei6km

上記メモに下記を追加する。

diff は下記の内容を貼り付けてある。
https://github.com/hankei6km/test-functions-framework-pubsub-ts/pull/14/commits/3e64e5358a9f3809b410f3bb5fc57d02c2644964


上記をふまえて diff からコミットメッセージを生成してみる

diff --git a/src/lib/reqid.ts b/src/lib/reqid.ts
index f26faff..4380d78 100644
--- a/src/lib/reqid.ts
+++ b/src/lib/reqid.ts
@@ -70,6 +70,7 @@ export async function dec(
 export type ReqInfo = {
   /**
    * The id of subscription that is used to receive response from user.
+   * it has prefix with `req-`
    */
   sunbscription: string
   /**
@@ -105,7 +106,7 @@ export type MakeReqInfoParams = {
  * @returns the information data.
  */
 export async function getReqId(params: MakeReqInfoParams): Promise<ReqInfo> {
-  const sunbscription = randomUUID()
+  const sunbscription = `req-${randomUUID()}`
   const filter = createHash('sha256')
     .update(sunbscription, 'utf8')
     .digest('hex')
diff --git a/test/index.integration.http.spec.ts b/test/index.integration.http.spec.ts
index 5e2dccd..7e6038a 100644
--- a/test/index.integration.http.spec.ts
+++ b/test/index.integration.http.spec.ts
@@ -12,7 +12,7 @@ import type { getReqId } from '../src/lib/reqid.js'
 // topics
 const topid = 'test-integration-topic-id'
 // subscriptions
-const sunbscription = 'test-subscription'
+const sunbscription = 'req-test-subscription'
 const filter = 'test-fileter'
 const handleId = 'test-handleid'
 
diff --git a/test/index.unit.http.spec.ts b/test/index.unit.http.spec.ts
index d2be91e..8209fbd 100644
--- a/test/index.unit.http.spec.ts
+++ b/test/index.unit.http.spec.ts
@@ -17,7 +17,7 @@ import type { getReqId } from '../src/lib/reqid.js'
 // topics
 const topid = 'test-unit-topic-id'
 // subscriptions
-const sunbscription = 'test-subscription'
+const sunbscription = 'req-test-subscription'
 const filter = 'test-fileter'
 const handleId = 'test-handleid'
 
diff --git a/test/lib/reqid.spec.ts b/test/lib/reqid.spec.ts
index 54e3b6a..7454794 100644
--- a/test/lib/reqid.spec.ts
+++ b/test/lib/reqid.spec.ts
@@ -96,9 +96,9 @@ describe('getReqId', () => {
     const { mockCreateCipheriv } = (mockCrypto as any)._getMocks()
 
     const i = await getReqId({ password, salt, sheetId: '', bundleId: '' })
-    expect(i.sunbscription).toEqual('50a11b0b-fea7-47b3-9934-b2191b5b6b29') // randomUUID を固定してあるので、常に同じ値.
+    expect(i.sunbscription).toEqual('req-50a11b0b-fea7-47b3-9934-b2191b5b6b29') // randomUUID を固定してあるので、常に同じ値.
     expect(i.filter).toEqual(
-      'cb6964b653b386c11b6a2b2c160e4d6442b21c8865b1f7f05d6f4f7cd03d752c'
+      '00fc2b4541cfc9128161c10a88d1bda33f0fa90416dfbac1e357e170ed68e90b'
     ) // randomUUID を固定してあるので、常に同じ値.
 
     // handleId はメソッドをコールしていたら暗号化されているだろう、ということにする.
hankei6kmhankei6km

上記のコードブロックを選択し ctrl+j で「コミットメッセージを生成してください。」と入力すると下記のように生成された。


feat: update reqid.ts

Add prefix req- to sunbscription on getReqId function to identify it.

Details

  • sunbscription is a subscription id that is used to receive response from user. Add prefix req- to it to identify it as a request subscription.
  • Update getReqId function to add prefix req- to sunbscription.
  • Update test/index.integration.http.spec.ts, test/index.unit.http.spec.ts, and test/lib/reqid.spec.ts to use req-test-subscription as subscription name.
hankei6kmhankei6km

生成されたメッセージは良いようなそうでもないような感じだけど、手順的には「切り貼りするのはめんどう」だった。

次からは diff のコピペだけになるからもう少し楽だけど、実際に使ってみるかはちょっと悩ましいところ(すなおにそれ用の拡張機能を探せという話でもある)。

hankei6kmhankei6km

別の diff で試してみた。
上で試したメモに見出しと diff のコードブロックを追加して AI の「続きを書く」を実行。


別のコミットのメッセージを生成

diff --git a/package.json b/package.json
index 8b28e39..cf804d6 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,9 @@
   },
   "scripts": {
     "start": "npm run build && node dist/main.js",
+    "debug": "npm run build:debug && node --inspect dist/main.js",
     "build": "npm run clean && tsc && rimraf dist/test && mv dist/src/* dist/ && rimraf dist/src",
+    "build:debug": "npm run clean && tsc --sourceMap --sourceRoot \"${PWD}\" && rimraf dist/test && mv dist/src/* dist/ && rimraf dist/src",
     "test": "node --experimental-vm-modules node_modules/.bin/jest",
     "lint:type-check": "tsc --noEmit",
     "clean": "rimraf \"dist/\"",
hankei6kmhankei6km

生成されたコミットメッセージ。


chore: add debug script

Add debug script to package.json to start node with inspect option and build:debug script to compile with source map.


type を使い分けてくれたのはちょっと意外だった(正直なところ今回も feat にされるかと予想していた)。

hankei6kmhankei6km

いまのメモに「よいコミットメッセージとは」的な記事の引用などを貼り付けておいて、その下に diff を貼り付けたら、さらに良くなりそうな気がしないでもない、かな。

hankei6kmhankei6km

さらに別のコミットメッセージを生成しようとしたのだが

下記の diff だとファイル別の変更点が列挙されるだけだった。変更箇所が多すぎるという気もするので、AI がそれっぽくないメッセージを生成したら、変更の仕方が悪いという風に考えるのもありかもしれない。

長いので折りたたみます
diff --git a/src/lib/notion.ts b/src/lib/notion.ts
index 63a18cd..a053018 100644
--- a/src/lib/notion.ts
+++ b/src/lib/notion.ts
@@ -29,9 +29,25 @@ export function pageParams(repo: RepoItem): {
         }
       ]
     },
+    name: {
+      rich_text: [
+        {
+          type: 'text',
+          text: { content: repo.name }
+        }
+      ]
+    },
     title: {
       title: [{ type: 'text', text: { content: repo.nameWithOwner } }]
     },
+    owner: {
+      rich_text: [
+        {
+          type: 'text',
+          text: { content: repo.owner.login }
+        }
+      ]
+    },
     //openGraphImageUrl: {
     //  files: [
     //    {
@@ -46,6 +62,9 @@ export function pageParams(repo: RepoItem): {
     repositoryTopics: {
       multi_select: (repo.repositoryTopics || []).map(({ name }) => ({ name }))
     },
+    pushedAt: {
+      date: { start: repo.pushedAt }
+    },
     updatedAt: {
       date: { start: repo.updatedAt }
     },
@@ -61,7 +80,7 @@ export async function send(client: Client, databaseId: string, repo: RepoItem) {
     .query({
       database_id: databaseId,
       filter: {
-        property: 'name',
+        property: 'title',
         title: {
           equals: repo.nameWithOwner
         }
diff --git a/src/lib/repo.ts b/src/lib/repo.ts
index 4c51851..129bd3b 100644
--- a/src/lib/repo.ts
+++ b/src/lib/repo.ts
@@ -2,7 +2,10 @@ export type RepoItem = {
   createdAt: string
   description: string
   nameWithOwner: string
+  name: string
   openGraphImageUrl: string
+  owner: { login: string; id?: string }
+  pushedAt: string
   repositoryTopics: Record<'name', string>[] | null
   updatedAt: string
   url: string
diff --git a/src/lib/validate.ts b/src/lib/validate.ts
index 679cb20..6cf5f70 100644
--- a/src/lib/validate.ts
+++ b/src/lib/validate.ts
@@ -10,8 +10,11 @@ export const RepoItemSchema = {
   type: 'object',
   required: [
     'createdAt',
+    'name',
     'nameWithOwner',
     'openGraphImageUrl',
+    'owner',
+    'pushedAt',
     'updatedAt',
     'url'
   ],
@@ -23,6 +26,9 @@ export const RepoItemSchema = {
     description: {
       type: 'string'
     },
+    name: {
+      type: 'string'
+    },
     nameWithOwner: {
       type: 'string'
     },
@@ -30,6 +36,15 @@ export const RepoItemSchema = {
       type: 'string',
       format: 'uri'
     },
+    owner: {
+      type: 'object',
+      required: ['login'],
+      properties: {
+        login: {
+          type: 'string'
+        }
+      }
+    },
     repositoryTopics: {
       type: ['array', 'null'],
       items: {
@@ -42,6 +57,10 @@ export const RepoItemSchema = {
         }
       }
     },
+    pushedAt: {
+      type: 'string',
+      format: 'date-time'
+    },
     updatedAt: {
       type: 'string',
       format: 'date-time'
diff --git a/test/lib/notion.spec.ts b/test/lib/notion.spec.ts
index 721cb30..f70bee3 100644
--- a/test/lib/notion.spec.ts
+++ b/test/lib/notion.spec.ts
@@ -8,9 +8,14 @@ describe('pageParams', () => {
         createdAt: '2022-04-11T07:40:07Z',
         description:
           'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/8a871d34480686c2e48e3dd1252aa8239e6564ed851beb3c77f174b138afea4c/hankei6km/gas-feed2notion',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: [
           {
             name: 'google-apps-script'
@@ -28,6 +33,7 @@ describe('pageParams', () => {
             name: 'typescript'
           }
         ],
+        pushedAt: '2023-02-08T08:10:47Z',
         updatedAt: '2023-02-08T08:10:47Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
@@ -55,9 +61,29 @@ describe('pageParams', () => {
             }
           ]
         },
+        name: {
+          rich_text: [
+            {
+              type: 'text',
+              text: {
+                content: 'aaaaa'
+              }
+            }
+          ]
+        },
         title: {
           title: [{ type: 'text', text: { content: 'hankei6km/aaaaa' } }]
         },
+        owner: {
+          rich_text: [
+            {
+              type: 'text',
+              text: {
+                content: 'hankei6km'
+              }
+            }
+          ]
+        },
         repositoryTopics: {
           multi_select: [
             {
@@ -77,6 +103,9 @@ describe('pageParams', () => {
             }
           ]
         },
+        pushedAt: {
+          date: { start: '2023-02-08T08:10:47Z' }
+        },
         updatedAt: {
           date: { start: '2023-02-08T08:10:47Z' }
         },
@@ -90,10 +119,16 @@ describe('pageParams', () => {
       pageParams({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: null,
+        pushedAt: '2022-02-23T13:55:00Z',
         updatedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
@@ -120,12 +155,35 @@ describe('pageParams', () => {
             }
           ]
         },
+        name: {
+          rich_text: [
+            {
+              type: 'text',
+              text: {
+                content: 'aaaaa'
+              }
+            }
+          ]
+        },
         title: {
           title: [{ type: 'text', text: { content: 'hankei6km/aaaaa' } }]
         },
+        owner: {
+          rich_text: [
+            {
+              type: 'text',
+              text: {
+                content: 'hankei6km'
+              }
+            }
+          ]
+        },
         repositoryTopics: {
           multi_select: []
         },
+        pushedAt: {
+          date: { start: '2022-02-23T13:55:00Z' }
+        },
         updatedAt: {
           date: { start: '2022-02-23T13:55:00Z' }
         },
@@ -142,10 +200,16 @@ describe('send', () => {
   const repo = {
     createdAt: '2022-02-05T14:16:25Z',
     description: '',
+    name: 'aaaaa',
     nameWithOwner: 'hankei6km/aaaaa',
     openGraphImageUrl:
       'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+    owner: {
+      id: 'abc123',
+      login: 'hankei6km'
+    },
     repositoryTopics: null,
+    pushedAt: '2022-02-23T13:55:00Z',
     updatedAt: '2022-02-23T13:55:00Z',
     url: 'https://github.com/hankei6km/aaaaa'
   }
@@ -157,7 +221,7 @@ describe('send', () => {
     expect(mockClient.databases.query).toBeCalledWith({
       database_id: databaseId,
       filter: {
-        property: 'name',
+        property: 'title',
         title: {
           equals: repo.nameWithOwner
         }
@@ -178,7 +242,7 @@ describe('send', () => {
     expect(mockClient.databases.query).toBeCalledWith({
       database_id: databaseId,
       filter: {
-        property: 'name',
+        property: 'title',
         title: {
           equals: repo.nameWithOwner
         }
diff --git a/test/lib/reposition.spec.ts b/test/lib/reposition.spec.ts
index 693e5c0..f2e116e 100644
--- a/test/lib/reposition.spec.ts
+++ b/test/lib/reposition.spec.ts
@@ -23,19 +23,31 @@ describe('reposition', () => {
       JSON.stringify({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: null,
+        pushedAt: '2022-02-23T13:55:00Z',
         updatedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
       }),
       JSON.stringify({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
+        pushedAt: '2022-02-23T13:55:00Z',
         repositoryTopics: null,
         updatedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
@@ -59,11 +71,17 @@ describe('reposition', () => {
       JSON.stringify({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
         repositoryTopics: null,
         updatedAt: '2022-02-23T13:55:00Z',
+        pushedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
       }),
       JSON.stringify({})
@@ -87,10 +105,16 @@ describe('reposition', () => {
       JSON.stringify({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'hankei6km/aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: null,
+        pushedAt: '2022-02-23T13:55:00Z',
         updatedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
diff --git a/test/lib/validate.spec.ts b/test/lib/validate.spec.ts
index b712349..f113554 100644
--- a/test/lib/validate.spec.ts
+++ b/test/lib/validate.spec.ts
@@ -7,9 +7,14 @@ describe('validateRepoItem', () => {
         createdAt: '2022-04-11T07:40:07Z',
         description:
           'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/8a871d34480686c2e48e3dd1252aa8239e6564ed851beb3c77f174b138afea4c/hankei6km/gas-feed2notion',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: [
           {
             name: 'google-apps-script'
@@ -27,6 +32,7 @@ describe('validateRepoItem', () => {
             name: 'typescript'
           }
         ],
+        pushedAt: '2023-02-08T08:10:47Z',
         updatedAt: '2023-02-08T08:10:47Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
@@ -35,10 +41,16 @@ describe('validateRepoItem', () => {
       validateRepoItem({
         createdAt: '2022-02-05T14:16:25Z',
         description: '',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           'https://opengraph.githubassets.com/0e9a92dd721c4e6cb2b82df96a66133ac93d43c4233159c1d1c3d1bc420a4fd2/hankei6km/chanpuru',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: null,
+        pushedAt: '2022-02-23T13:55:00Z',
         updatedAt: '2022-02-23T13:55:00Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
@@ -51,12 +63,18 @@ describe('validateRepoItem', () => {
         createdAt: 'invalid date',
         description:
           'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           '<https://opengraph.githubassets.com/8a871d34480686c2e48e3dd1252aa8239e6564ed851beb3c77f174b138afea4c/hankei6km/gas-feed2notion>',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: {
           name: 'invalid topic'
         },
+        pushedAt: '2023-02-08T08:10:47Z',
         updatedAt: '2023-02-08T08:10:47Z',
         url: 'https://github.com/hankei6km/aaaaa'
       })
@@ -66,10 +84,16 @@ describe('validateRepoItem', () => {
         createdAt: '2022-04-11T07:40:07Z',
         description:
           'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+        name: 'aaaaa',
         nameWithOwner: 'hankei6km/aaaaa',
         openGraphImageUrl:
           '<https://opengraph.githubassets.com/8a871d34480686c2e48e3dd1252aa8239e6564ed851beb3c77f174b138afea4c/hankei6km/gas-feed2notion>',
+        owner: {
+          id: 'abc123',
+          login: 'hankei6km'
+        },
         repositoryTopics: null,
+        pushedAt: '2023-02-08T08:10:47Z',
         updatedAt: '2023-02-08T08:10:47Z',
         url: '<https://github.com/hankei6km/aaaa>'
       })