Cloudflare WARP クライアントの最新リリース情報を Workers で検知してメール通知する

# RSS リンク

:::note info
Cloudflare WARP クライアントでアップデートを確認する際に使われている RSS リンクをデバッグ時に発見したので、下記リンクを使って RSS 購読可能です。
:::

https://gist.github.com/kyouheicf/9a31debe7c1b1c6a239e0f58f07ff88b

# 目的
Cloudflare WARP クライアントがリリースされたタイミングで通知が来る仕組みを Workers を使って作ります。

```mermaid:
graph TB
AC[App Center]
subgraph Cloudflare
Workers
KV
end
Workers --> |2.#nbsp;GET Release|AC

Workers --> |1.#nbsp;Cron Trigger|Workers
Workers ---> |4.#nbsp;PUT|KV
KV ---> |3.#nbsp;GET|Workers

Workers ---> |5.#nbsp;Email Workers|Email[Send Email]
```

# 成果物

https://github.com/kyouheicf/warp-release

# App Center
## リリース一覧
macOS と Windows の WARP リリース情報は以下のようなリンクから取得することができます。
このリリース ID を使って詳細なリリースノートや最新バージョンかどうかの確認をします。

- [Download WARP · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/download-warp/)

https://install.appcenter.ms/api/v0.1/apps/cloudflare/1.1.1.1-macos/distribution_groups/beta/public_releases

```json:
% curl -s 'https://install.appcenter.ms/api/v0.1/apps/cloudflare/1.1.1.1-macos/distribution_groups/beta/public_releases' | jq '.[0]'     
{
  "id": 2989,
  "short_version": "2023.12.292.1",
  "version": "20231216.5",
  "origin": "appcenter",
  "uploaded_at": "2023-12-16T03:40:27.993Z",
  "mandatory_update": false,
  "enabled": true,
  "is_external_build": false
}
```

## 個別リリースノート
個別のリリースノートは、以下のようなリンクから取得できます。

https://install.appcenter.ms/api/v0.1/apps/cloudflare/1.1.1.1-macos/distribution_groups/beta/releases/2989

```json:
% curl -s 'https://install.appcenter.ms/api/v0.1/apps/cloudflare/1.1.1.1-macos/distribution_groups/beta/releases/2989' | jq        
{
  "app_name": "1.1.1.1-macOS",
  "app_display_name": "Cloudflare WARP macOS Beta",
  "app_os": "macOS",
  "app_icon_url": "https://coreservicesstorgeprod.blob.core.windows.net/app-avatar-container/0e33d9ad-f2bd-4842-b088-7ee53aa4ec99?st=2023-12-27T05%3A07%3A53Z&se=2024-01-10T06%3A07%3A53Z&sp=r&sv=2018-03-28&sr=b&sig=pNRLSxmzbvQ3CgToHvW059AXa2KmTo%2FgwwjTnrKm0DQ%3D",
  "owner": {
    "name": "Cloudflare",
    "display_name": "Cloudflare"
  },
  "is_external_build": false,
  "origin": "appcenter",
  "id": 2989,
  "version": "20231216.5",
  "short_version": "2023.12.292.1",
  "size": 70335499,
  "min_os": null,
  "device_family": null,
  "bundle_identifier": "8e1cda87399634bf8d4da269812ed3c4",
  "fingerprint": "2000c6e1124717ee424e7cacc0e8fbf8",
  "uploaded_at": "2023-12-16T03:40:27.993Z",
  "download_url": "https://appcenter-filemanagement-distrib4ede6f06e.azureedge.net/f86cf4b2-158e-4cec-9128-d620e0cd02c6/Cloudflare_WARP.pkg?sv=2019-02-02&sr=c&sig=b08SGN3qt7njLwyZGHNqTukKnrXEz8W8fkqwdCD6Ttg%3D&se=2023-12-29T09%3A34%3A00Z&sp=r",
  "install_url": "https://appcenter-filemanagement-distrib4ede6f06e.azureedge.net/f86cf4b2-158e-4cec-9128-d620e0cd02c6/Cloudflare_WARP.pkg?sv=2019-02-02&sr=c&sig=b08SGN3qt7njLwyZGHNqTukKnrXEz8W8fkqwdCD6Ttg%3D&se=2023-12-29T09%3A34%3A00Z&sp=r",
  "mandatory_update": false,
  "enabled": true,
  "fileExtension": "pkg",
  "is_latest": true,
  "release_notes": "\nThis release contains exciting new features and bug fixes for both DEX and notifications. Please take time over the next few weeks to play with the new functionality and let us know what you think on both the community forum and through your account teams.\n \n## Notable updates\n- Added ability for Client to display Gateway NETWORK and HTTP block notifications to the user (feature to be available in dash in the coming week).\n- Added ability for administrators to specify multiple configurations in MDM files that users can toggle between. This allows users to more easily switch between production and test environments or China customers to switch between their override endpoints within the UI.\n- Improved existing re-auth notifications to be more visible and time sensitive.\n- Fixed an issue where DEX tests would run before the client was fully connected.\n- Fixed minor UI issue for customers in Include Split tunnel mode where the client would incorrectly state \"Your internet is protected\" instead of only DNS and Included routes are protected.\n- Fixed an issue where the GUI app would be unresponsive to clicks after waking up from sleep.\n- Fixed an issue where the re-authenticate button was not completely visible in the GUI.\n \n## Known issues\n- The new `display_name` MDM parameter that is part of the multiple configurations feature is not correctly working. For this release the name visible in the UI will be the organization value. A future beta release will correct this; it is safe to include this parameter in updated MDM files now.\n \nFor Zero Trust documentation please see: https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp\nFor Consumer documentation please see: https://developers.cloudflare.com/warp-client/\n",
  "is_udid_provisioned": null,
  "can_resign": null,
  "package_hashes": [],
  "destination_type": "group",
  "status": "available",
  "distribution_group_id": "8d228a4a-99fe-426c-ad9f-623db9d82323",
  "distribution_groups": [
    {
      "id": "8d228a4a-99fe-426c-ad9f-623db9d82323",
      "name": "Beta",
      "origin": "appcenter",
      "display_name": "Beta",
      "is_public": true
    }
  ]
}
```

# 参考：iOS アプリのリリース情報
以下の iTunes Search API から取得できる情報で検知が可能です。

- [ネイティブアプリのStore情報をAPIで取得する #iOS - Qiita](https://qiita.com/kurikazu/items/30be55103cf8b4744101)

```shell:
% curl -s 'https://itunes.apple.com/lookup?id=6443476492' | jq '.results[0] | {version:.version, currentVersionReleaseDate:.currentVersionReleaseDate, releaseNotes:.releaseNotes}'
{
  "version": "1.3",
  "currentVersionReleaseDate": "2024-01-04T23:00:03Z",
  "releaseNotes": "New Cloudflare One app changes\n \n- The app displays Gateway Network and HTTP block notifications\n- Fixed an issue with iOS 17.x with the iPhone entering a loop while trying to connect\n- Fixed an issue to resolve DNS servers when the default path DNS servers is empty\n- Fix a problem with re-auth notification banners not appearing after the device sleeps\n- Delivered additional bug fixes, connectivity improvements, and increased stability\n  \n   Zero Trust docs: https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp"
}
```

# Cloudflare Workers

## KV バインディング
KV のネームスペースを作成してバインディングします。

```shell:
wrangler kv:namespace create WARP_RELEASE_KV
```

```toml:wrangler.toml
kv_namespaces = [
	 { binding = "WARP_RELEASE_KV", id = "xxxxx"}
]
```

中身は以下のような操作で確認できます。

```shell:
wrangler kv:key list --binding WARP_RELEASE_KV

wrangler kv:key put 2024-01-10 2989 --binding WARP_RELEASE_KV

wrangler kv:key get 2024-01-11 --binding WARP_RELEASE_KV
```

## メール送信バインディング
以下のドキュメントに従って構成します。

- [Send emails from Workers · Cloudflare Email Routing docs](https://developers.cloudflare.com/email-routing/email-workers/send-email-workers/)

```toml:wrangler.toml
send_email = [
    {type = "send_email", name = "EMAIL_WORKER", destination_address = "you@example.com"},
]
```

メール送信の動作確認には、デプロイして確認しましょう。

> - [Cloudflare Turnstile & Email Routingで実現するコンタクトフォーム](https://zenn.dev/naporin24690/articles/11d4ee3ecb3257)
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/1ef8580b-7d3f-b720-7d6a-4e0b7f3d44ba.png)

## シークレット設定
以下のコマンドでメールの送信元・受信先をシークレット変数で設定します。

```
wrangler secret put SENDER
wrangler secret put RECIPIENT 
```

`SENDER` はアカウントに登録済みのドメイン、`RECIPIENT` は Email Routing で Verified されたアドレスである必要があります。

## Cron Trigger
以下の例では、毎日午前10時に Workers が起動して最新リリース情報を検知するように設定します。

```toml:wrangler.toml
# min hour day month weekdays (Cron Triggers execute on UTC time.)
# every day at 10 AM JST
[triggers]
crons = ["0 1 * * *"]
```

# 動作確認
以下のコマンドでデプロイできます。

```shell:
wrangler deploy
```

## バージョン検知なし
リリース ID が前日と同じ場合は、何もしません。

```json:
{
  "outcome": "ok",
  "scriptName": "warp-release",
  "diagnosticsChannelEvents": [],
  "exceptions": [],
  "logs": [
    {
      "message": [
        "cron processed: event scheduledTime date jst = 2024-01-11 09:53:00"
      ],
      "level": "log",
      "timestamp": 1704934389862
    },
    {
      "message": [
        "Current Release ID = 3022, Type = number"
      ],
      "level": "log",
      "timestamp": 1704934390092
    },
    {
      "message": [
        "Previous Release ID = 3022, Type = string"
      ],
      "level": "log",
      "timestamp": 1704934390198
    },
    {
      "message": [
        "No New Version is released"
      ],
      "level": "log",
      "timestamp": 1704934390198
    }
  ],
  "eventTimestamp": 1704934389855,
  "event": {
    "cron": "53 * * * *",
    "scheduledTime": 1704934389000
  },
  "id": 5
}
```

## 新バージョン検知
リリース ID が前日と異なる場合は、該当のバージョンに関するリリースノートをメール送信します。

```json:
{
  "outcome": "ok",
  "scriptName": "warp-release",
  "diagnosticsChannelEvents": [],
  "exceptions": [],
  "logs": [
    {
      "message": [
        "cron processed: event scheduledTime date jst = 2024-01-11 09:43:00"
      ],
      "level": "log",
      "timestamp": 1704933798754
    },
    {
      "message": [
        "Current Release ID = 3022, Type = number"
      ],
      "level": "log",
      "timestamp": 1704933798952
    },
    {
      "message": [
        "Previous Release ID = 2989, Type = string"
      ],
      "level": "log",
      "timestamp": 1704933799048
    },
    {
      "message": [
        "New version release is detected",
        "Latest Release: Cloudflare WARP macOS Beta 2024.1.8.1 (1/4/2024, 6:21:39 AM)"
      ],
      "level": "log",
      "timestamp": 1704933799504
    }
  ],
  "eventTimestamp": 1704933798746,
  "event": {
    "cron": "43 * * * *",
    "scheduledTime": 1704933798000
  },
  "id": 2
}
```

## 受信できたメール
以下のようなメールが受信できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/119c191a-ac39-abbc-101f-63f69bff9301.png)

# まとめ
Cloudflare Workers だけで意外と簡単にメール送信までやりたいことができました。

こうした開発体験を経ると、Cloudflare の良さが改めてわかります。