Closed28

linear-webhook の new type への対応

Linear 側のアップデートで Webhook のタイプが増えた。

https://linear.app/changelog/2021-02-04-new-webhook-types

types: issue labels, comment reactions, cycles and projects.

新たに、ラベル、コメントへのリアクション、サイクル、プロジェクトの追加、更新、削除に対して Webhook を飛ばすようになった。

これに対応したい

まずはラベル。
以前からIssueにラベルを貼り付けたらIssueUpdateイベントとなってwebhookは飛んでいた。
そこら辺は変わってない模様

Team Settings -> Labels -> New label でラベルを作成した

{
    "action": "create",
    "createdAt": "2021-02-07T09:17:51.393Z",
    "data": {
        "id": "13aa50db-xxxx-xxxx-xxxx-1cdd26695e65",
        "createdAt": "2021-02-07T09:17:51.393Z",
        "updatedAt": "2021-02-07T09:17:51.393Z",
        "name": "new label",
        "color": "#5a450d",
        "teamId": "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1",
        "creatorId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39"
    },
    "type": "IssueLabel"
}

IssueLabelというtypeになるらしい。Labelではないんだ。
これに対応する

今までのaction: "create"は必ずurlメンバを持っていたが、CreateIssueLabelはそれを持たない。optional property にする

次は UpdateIssueLabel を確認する
ラベル名を変更した

{
    "action": "update",
    "createdAt": "2021-02-07T09:33:32.156Z",
    "data": {
        "id": "13aa50db-xxxx-xxxx-xxxx-1cdd26695e65",
        "createdAt": "2021-02-07T09:17:51.393Z",
        "updatedAt": "2021-02-07T09:33:32.156Z",
        "name": "update new label",
        "color": "#5a450d",
        "teamId": "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1",
        "creatorId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39"
    },
    "updatedFrom": {
        "updatedAt": "2021-02-07T09:17:51.393Z",
        "archivedAt": null,
        "name": "new label",
        "description": null
    },
    "type": "IssueLabel"
}

最後に RemoveIssueLabel を確認する。

{
    "action": "remove",
    "createdAt": "2021-02-07T09:38:46.255Z",
    "data": {
        "id": "13aa50db-xxxx-xxxx-xxxx-1cdd26695e65",
        "createdAt": "2021-02-07T09:17:51.393Z",
        "updatedAt": "2021-02-07T09:33:32.156Z",
        "archivedAt": "2021-02-07T09:38:46.255Z",
        "name": "update new label",
        "color": "#5a450d",
        "teamId": "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1",
        "creatorId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39"
    },
    "type": "IssueLabel"
}

dataarchivedAtが増えた

RemoveIssueLabel のみarchivedAtを持っているので、CreateIssueLabel、UpdateIssueLabelが持つdataからarchivedAtをOmit

export interface CreateIssueLabel extends Create, IssueLabel {
  data: Omit<IssueLabelDate, "archivedAt">;
}
export interface UpdateIssueLabel extends Update, IssueLabel {
  data: Omit<IssueLabelDate, "archivedAt">;
}

今回はOmitしてるけど、これRemoveIssueLabelのdataにarchivedAtを追加した方がいいのだろうか?

export interface RemoveIssueLabel extends Remove, IssueLabel {
  data: IssueLabelDate & {
    archivedAt: ISOString;
  };
}

こっちの方が同じ変更をCreateIssueLabelとUpdateIssueLabelに入れなくて済むから良い?
とりあえず後者を採用しよう

進捗

  • IssueLabel
  • CommentReaction
  • Cycle
  • Project

コメントにリアクションする

{
    "action": "create",
    "createdAt": "2021-02-07T10:10:55.083Z",
    "data": {
        "id": "c6d50a94-xxxx-xxxx-xxxx-8a552952a50e",
        "createdAt": "2021-02-07T10:10:55.083Z",
        "updatedAt": "2021-02-07T10:10:55.083Z",
        "emoji": "white_check_mark",
        "userId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
        "commentId": "fd58dfb7-xxxx-xxxx-xxxx-759c3c2437d5",
        "comment": {
            "id": "fd58dfb7-xxxx-xxxx-xxxx-759c3c2437d5",
            "body": "new comment",
            "userId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39"
        },
        "user": {
            "id": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
            "name": "hoge@example.com"
        }
    },
    "type": "Reaction"
}

CreateReactionが飛んでくる

なぜかついでにUpdateCommentが飛んでくる

{
    "action": "update",
    "createdAt": "2021-02-07T10:10:55.083Z",
    "data": {
        "id": "fd58dfb7-xxxx-xxxx-xxxx-759c3c2437d5",
        "createdAt": "2021-02-07T10:10:51.760Z",
        "updatedAt": "2021-02-07T10:10:55.083Z",
        "body": "new comment",
        "userId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
        "issueId": "396f4eb9-xxxx-xxxx-xxxx-33fe2fcca5e0",
        "issue": {
            "id": "396f4eb9-xxxx-xxxx-xxxx-33fe2fcca5e0",
            "title": "hihi"
        },
        "user": {
            "id": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
            "name": "hoge@example.com"
        }
    },
    "updatedFrom": {
        "updatedAt": "2021-02-07T10:10:51.760Z",
        "archivedAt": null,
        "editedAt": null
    },
    "url": "https://linear.app/xxxx/issue/KOR-13/hihi#comment-fd58dfb7",
    "type": "Comment"
}

以前はコメントにリアクションをするとUpdateCommentイベントとしてwebhookが飛んでいた。

{
  action: "update",
  createdAt: "2021-01-31T13:13:07.588Z",
  data: {
....
    reactions: [],
  },
  updatedFrom: {
    updatedAt: "2021-01-31T13:13:00.988Z",
    archivedAt: null,
    body: "aaaaa",
    editedAt: null,
  },
  url: "https://linear.app/xxxx/issue/KOR-15/subissue#comment-00c2b179",
  type: "Comment",
}

data.reactionsという配列に下のような構造でリアクションが含まれていた。

interface Reaction {
  id: ReactionId;
  emoji: string;
  userId: UserId;
}

今回の更新でUpdateCommentイベントにリアクションは含まれなくなった模様。なのにUpdateCommentイベントが飛んでくる。冗長では?

とりあえずComment周りを修正してCreateReactionWebhookインタフェースを作成。
次はReactionを取り消してみる

リアクション消そうとしてるのに押しても消えねー

あ、時間差で消えた。

リアクション消してもRemoveReactionもUpdateReactionも飛んでこない。
UpdateCommentは相変わらずくる。
これだとリアクション取り消してもWebhookじゃ検知できない。
これもバグじゃね?

進捗

  • IssueLabel
  • Reaction(createのみ)
  • Cycle
  • Project

Cycle 名を rename

長い

{
    "action": "update",
    "createdAt": "2021-02-07T11:54:03.602Z",
    "data": {
        "id": "8becebd5-xxxx-xxxx-xxxx-5a4c46206590",
        "createdAt": "2021-01-30T11:21:04.585Z",
        "updatedAt": "2021-02-07T11:54:03.602Z",
        "number": 1,
        "name": "rename cycle",
        "startsAt": "2021-01-24T15:00:00.000Z",
        "endsAt": "2021-02-07T15:00:00.000Z",
        "issueCountHistory": [
            0,
            0,
            0,
            0,
            0,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1
        ],
        "completedIssueCountHistory": [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
        ],
        "scopeHistory": [
            0,
            0,
            0,
            0,
            0,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1
        ],
        "completedScopeHistory": [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
        ],
        "teamId": "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1",
        "uncompletedIssuesUponCloseIds": []
    },
    "updatedFrom": {
        "updatedAt": "2021-02-06T15:00:01.678Z",
        "archivedAt": null,
        "name": null,
        "completedAt": null
    },
    "type": "Cycle"
}

今度は'Change cycle start time...'してみた

{
    "action": "update",
    "createdAt": "2021-02-07T12:05:20.358Z",
    "data": {
        "id": "397b115e-xxxx-xxxx-xxxx-5012096c7484",
        "createdAt": "2021-01-30T11:21:04.585Z",
        "updatedAt": "2021-02-07T12:05:20.358Z",
        "number": 3,
        "startsAt": "2021-03-21T15:00:00.000Z",
        "endsAt": "2021-04-04T15:00:00.000Z",
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "teamId": "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1",
        "uncompletedIssuesUponCloseIds": []
    },
    "updatedFrom": {
        "updatedAt": "2021-01-30T11:21:04.585Z",
        "archivedAt": null,
        "name": null,
        "startsAt": "2021-02-21T15:00:00.000Z",
        "endsAt": "2021-03-07T15:00:00.000Z",
        "completedAt": null
    },
    "type": "Cycle"
}

data.nameが消えた。多分リネームしないとnameは存在しないのだろう。optionalにする
updatedFromもstartsAtとendsAtが増えた

進捗

  • IssueLabel
  • Reaction(createのみ)
  • Cycle(updateのみ)
  • Project

Project の作成

基本

{
    "action": "create",
    "createdAt": "2021-02-07T12:18:42.073Z",
    "data": {
        "id": "14449f5f-xxxx-xxxx-xxxx-155b5c08af2a",
        "createdAt": "2021-02-07T12:18:42.073Z",
        "updatedAt": "2021-02-07T12:18:42.073Z",
        "name": "new Project",
        "description": "",
        "slugId": "87cf626a561e",
        "color": "#bec2c8",
        "state": "planned",
        "creatorId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
        "milestoneId": "b89dd730-xxxx-xxxx-xxxx-b195ab3144da",
        "sortOrder": 1109.12,
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "slackNewIssue": true,
        "slackIssueComments": true,
        "slackIssueStatuses": true,
        "teamIds": [
            "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1"
        ],
        "memberIds": []
    },
    "url": "https://linear.app/xxxx/project/new-project-87cf626a561e",
    "type": "Project"
}

全部入り

{
    "action": "create",
    "createdAt": "2021-02-07T12:21:05.729Z",
    "data": {
        "id": "5ad6280f-xxxx-xxxx-xxxx-b869cfa62b33",
        "createdAt": "2021-02-07T12:21:05.729Z",
        "updatedAt": "2021-02-07T12:21:05.729Z",
        "name": "fffff",
        "description": "aaaa",
        "slugId": "37f87fe3d558",
        "icon": "Page",
        "color": "#0f7488",
        "state": "started",
        "creatorId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
        "leadId": "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39",
        "milestoneId": "b89dd730-xxxx-xxxx-xxxx-b195ab3144da",
        "targetDate": "2021-02-11",
        "startedAt": "2021-02-07T12:21:05.748Z",
        "sortOrder": 2031.02,
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "slackNewIssue": true,
        "slackIssueComments": true,
        "slackIssueStatuses": true,
        "teamIds": [
            "eeaa0cbd-xxxx-xxxx-xxxx-1c701c3485f1"
        ],
        "memberIds": [
            "80e102b0-xxxx-xxxx-xxxx-044bcfb4cd39"
        ]
    },
    "url": "https://linear.app/xxxx/project/fffff-37f87fe3d558",
    "type": "Project"
}

createは対応した。
次はupdate

なんか二つきたんだが

{
    "action": "update",
    "createdAt": "2021-02-07T12:41:09.314Z",
    "data": {
        "id": "5ad6280f-eeef-435e-949f-b869cfa62b33",
        "createdAt": "2021-02-07T12:21:05.729Z",
        "updatedAt": "2021-02-07T12:41:09.314Z",
        "name": "rename project",
        "description": "aaaa",
        "slugId": "37f87fe3d558",
        "icon": "Page",
        "color": "#0f7488",
        "state": "started",
        "creatorId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "leadId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "milestoneId": "b89dd730-af60-4880-b408-b195ab3144da",
        "targetDate": "2021-02-11",
        "startedAt": "2021-02-07T12:21:05.748Z",
        "sortOrder": 2031.02,
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "slackNewIssue": true,
        "slackIssueComments": true,
        "slackIssueStatuses": true,
        "teamIds": [
            "eeaa0cbd-5902-4d57-a7ad-1c701c3485f1"
        ],
        "memberIds": [
            "80e102b0-4a45-44d4-93a8-044bcfb4cd39"
        ]
    },
    "updatedFrom": {
        "archivedAt": null,
        "completedAt": null,
        "canceledAt": null
    },
    "url": "https://linear.app/korosuke613/project/rename-project-37f87fe3d558",
    "type": "Project"
}
{
    "action": "update",
    "createdAt": "2021-02-07T12:41:09.314Z",
    "data": {
        "id": "5ad6280f-eeef-435e-949f-b869cfa62b33",
        "createdAt": "2021-02-07T12:21:05.729Z",
        "updatedAt": "2021-02-07T12:41:09.314Z",
        "name": "rename project",
        "description": "aaaa",
        "slugId": "37f87fe3d558",
        "icon": "Page",
        "color": "#0f7488",
        "state": "started",
        "creatorId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "leadId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "milestoneId": "b89dd730-af60-4880-b408-b195ab3144da",
        "targetDate": "2021-02-11",
        "startedAt": "2021-02-07T12:21:05.748Z",
        "sortOrder": 2031.02,
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "slackNewIssue": true,
        "slackIssueComments": true,
        "slackIssueStatuses": true,
        "teamIds": [
            "eeaa0cbd-5902-4d57-a7ad-1c701c3485f1"
        ],
        "memberIds": [
            "80e102b0-4a45-44d4-93a8-044bcfb4cd39"
        ]
    },
    "updatedFrom": {
        "name": "fffff",
        "updatedAt": "2021-02-07T12:21:05.729Z",
        "archivedAt": null,
        "completedAt": null,
        "canceledAt": null
    },
    "url": "https://linear.app/korosuke613/project/rename-project-37f87fe3d558",
    "type": "Project"
}

UpdateProject は特に変更なかった。

export interface UpdateProjectWebhook extends Update, Project {}

Project画面でIssueを作成したけどUpdateProjectイベントは発生せず、CreateIssueイベントが発生した。想定通り

Projectを削除
archivedAtが追加された

{
    "action": "remove",
    "createdAt": "2021-02-07T13:23:03.860Z",
    "data": {
        "id": "5ad6280f-eeef-435e-949f-b869cfa62b33",
        "createdAt": "2021-02-07T12:21:05.729Z",
        "updatedAt": "2021-02-07T13:22:11.230Z",
        "archivedAt": "2021-02-07T13:23:03.860Z",
        "name": "rename project",
        "description": "aaaa",
        "slugId": "37f87fe3d558",
        "icon": "Page",
        "color": "#0f7488",
        "state": "canceled",
        "creatorId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "leadId": "80e102b0-4a45-44d4-93a8-044bcfb4cd39",
        "milestoneId": "b89dd730-af60-4880-b408-b195ab3144da",
        "targetDate": "2021-02-11",
        "startedAt": "2021-02-07T12:21:05.748Z",
        "canceledAt": "2021-02-07T13:22:11.227Z",
        "sortOrder": 2031.02,
        "issueCountHistory": [],
        "completedIssueCountHistory": [],
        "scopeHistory": [],
        "completedScopeHistory": [],
        "slackNewIssue": true,
        "slackIssueComments": true,
        "slackIssueStatuses": true,
        "teamIds": [
            "eeaa0cbd-5902-4d57-a7ad-1c701c3485f1"
        ],
        "memberIds": [
            "80e102b0-4a45-44d4-93a8-044bcfb4cd39"
        ]
    },
    "url": "https://linear.app/korosuke613/project/rename-project-37f87fe3d558",
    "type": "Project"
}

メモ
これアリかも?

type Create<T extends Webhook> = T & {
  url: string;
};
このスクラップは2021/02/07にクローズされました
作成者以外のコメントは許可されていません