プロダクト
Dagu がどこで動いていても、GitHub、Stripe、Slack からワークフローを起動する
Dagu v2.20 では、DAG の Webhook に Dagu Cloud 経由の公開 URL を付けられます。公開アドレスのないサーバーでも、GitHub、Stripe、Slack から DAG を起動できます。サーバーがオフラインの間、リクエストはサーバーを待ちます。
TL;DR Dagu v2.20 では、DAG の Webhook に Dagu Cloud 経由の公開 URL を付けられます。GitHub、Stripe、Slack、または Standard Webhooks に対応した送信元から、公開アドレスも、開いたポートも、トンネルもないサーバーの DAG を起動できます。サーバーがオフラインの間に届いたリクエストは、サーバーを待ちます。DAG の Webhook タブからオンにしてください。
Dagu の DAG にはどれも Webhook を付けられ、社内ネットワークの中からはこれまでも簡単に呼び出せました。問題は Webhook を送る側のサービスです。GitHub、Stripe、Slack はインターネット上にあり、Dagu サーバーはたいていそうではありません。プライベートサブネットの VM や、オフィスのマシンや、誰かのノート PC で動いています。
よくある答えは、ポートを開ける、トンネルを動かす、サーバーの前にリバースプロキシを置く、のいずれかです。どれも、動かし、守り、生かし続けるものが 1 つ増えます。しかも、リクエストが届いたちょうどそのときにサーバーが再起動中なら、どれも役に立ちません。
できること
- インターネット上のアドレス: URL は
hooks.dagu.shにあります。サーバーは HTTPS で Dagu Cloud へ外向きに接続し、サーバーへ内向きに接続するものはありません。 - 待ってくれるリクエスト: Dagu Cloud は、サーバーが受け取るまで、最大 7 日間リクエストを保持します。デプロイや再起動の最中に届いた push も、サーバーが戻れば実行を開始します。
- 1 リクエストにつき 1 実行: Dagu Cloud が同じリクエストを再送しても、開始する実行は最大 1 つです。
- 署名の検証: 送信元に GitHub、Stripe、Slack、Standard Webhooks のいずれかを選ぶと、その送信元の有効な署名がないリクエストを Dagu が拒否します。署名シークレットはサーバーから出ません。
- 必要なイベントだけ:
pushやpull_request.openedのようにイベントを並べると、それ以外はスキップされます。 - すべての配信の記録: カードには最近の配信と、それぞれがどう処理されたか、開始した実行へのリンクが表示されます。
GitHub で設定する
- サーバーを Dagu v2.20 以降に更新し、プランと機能 から Dagu コンソール に接続します。ワークスペースごとに 1 台は無料で接続できます。
- DAG を開いて Webhook タブを開き、Webhook がなければ作成します。
- 公開 URL のスイッチをオンにします。数秒で URL が表示されます。
- 送信元に GitHub を選び、イベント に
pushと入力して、送信元を保存 を選びます。Dagu が署名シークレットを作り、一度だけ表示します。 - GitHub のリポジトリの Settings › Webhooks で、URL を Payload URL に貼り付け、Content type を
application/jsonにして、シークレットを貼り付けます。
保存すると、GitHub は ping を送ります。ping は実行を開始しないので、カードにはスキップとして表示されます。コミットを push すると、次の行が 開始済み になり、実行へのリンクが付きます。
実行が受け取るもの
実行は、リクエストを 3 つの変数で受け取ります。
WEBHOOK_PAYLOAD: 送信元が送ったとおりのボディ。WEBHOOK_PAYLOAD_FILE: 同じボディを保存した非公開ファイルのパス。実行が終わると削除されます。WEBHOOK_HEADERS:webhook.forward_headersに並べたリクエストヘッダー。
ボディが大きくなりうるときは、ファイルを読んでください。Linux と macOS では 1 つの環境変数に入るのは 128 KiB 未満なので、それより大きなボディはファイルとしてだけステップに届きます。
webhook:
forward_headers:
- X-GitHub-Event
steps:
- id: deploy
run: |
branch=$(jq -r '.ref' "$WEBHOOK_PAYLOAD_FILE")
./scripts/deploy.sh "$branch"
制限
| 無料モニタリング | トライアル、Team、Pro | |
|---|---|---|
| サーバーごとの公開 URL | 1 個 | 1,000 個 |
| リクエストボディ | 512 KiB | 512 KiB |
| URL ごとのリクエスト | 1 分間に 60 件 | 1 分間に 60 件 |
| サーバーごとの待機中のリクエスト | 1,000 件 | 1,000 件 |
制限を超えた送信元には、黙って捨てるのではなく、Retry-After 付きの 429 のように、はっきりしたステータスコードが返ります。
Dagu Cloud に見えるもの
Dagu を自分のサーバーで動かすのは、ワークフローを手元に置くためです。だからこそ、途中で Dagu Cloud を通るものが何かは重要です。
- リクエストは一時的に: Dagu Cloud は、各リクエストのボディとヘッダーを、サーバーが受け取るまで、最長 7 日間だけ保存します。サーバーに渡す前に、
AuthorizationやCookieなどの認証情報とプロキシのヘッダーを取り除きます。 - トークンは保存しない: URL の末尾はランダムなトークンです。Dagu Cloud が保存するのは、その SHA-256 だけです。
- シークレットは受け取らない: 署名はサーバー上で、Dagu Cloud が受け取ることのないシークレットで検証します。
- サーバーから届くのはごくわずか: サーバーが送るのは、サーバー名、Dagu のバージョン、各配信をどう処理したかだけです。ワークフロー、ログ、出力がサーバーから出ることはありません。
URL をオフにすると、約 10 秒以内に URL が無効になり、待っていたリクエストも破棄されます。
試してみる
サーバーを v2.20 に更新して接続し、GitHub のリポジトリを 1 つ向けてみてください。公開 Webhook URL のドキュメントに、すべての送信元、それぞれが送るイベント、うまくいかないときに送信元に返るものをまとめています。質問やアイデアがあれば Discord で教えてください。
Written by
Daguプロジェクトのコントリビューター。
More from Yota Hamada