notebook

都内でWEB系エンジニアやってます。

GitHubActionsでBigQueryへクエリしたテーブル表示の結果をそのままSlackに流す

プライベートでTogglのデータやブログのデータなどさまざまなデータを収集してBigQueryに入れている

LookerStudioを使って可視化して定期的に見に行くというのも悪くはないが

毎日特定の数値だけ進捗を確認、把握したい場合だと自分はSlackに通知してそれを見るほうが良いと思っている

よくBigQueryにクエリを投げてJSONを受け取り、jqで整形してSlackに流して…というのを結構やっていたが、整形するのが結構面倒だなと思っていた

普通のテーブル表示(--format pretty)をそのまま投げても良いのでは?と思ってGitHubActionsで試してみた

サンプルのWorkflowファイルと関連するファイル

BigQueryへのアクセスはOIDCを使っているが今回は触れない

  • sample.yml
name: Pocket stats

on:
  workflow_dispatch:
    inputs:
      target_date:
        description: 'target date(%Y-%m-%d)'
        required: false

jobs:
  query_result_to_slack:
    runs-on: ubuntu-latest
    name: query
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v3
      - id: auth
        uses: google-github-actions/auth@v1.0.0
        with:
          create_credentials_file: true
          workload_identity_provider: projects/111111111111/locations/global/workloadIdentityPools/pool_name/providers/provider_name
          service_account: sa-name@sample-111111.iam.gserviceaccount.com
          access_token_lifetime: 300s

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v1.1.0

      - name: input time
        id: set_date
        run: |
          input_date=${{ github.event.inputs.target_date }}
          if [[ -z "$input_date" ]]; then
            target_date=$(date -d "7 day ago" +"%Y-%m-%d")
          else
            target_date=$input_date
          fi

          echo "target_date=$target_date" >> $GITHUB_OUTPUT

      - id: query
        name: gcloud
        run: |
          result=$(bq query --bigqueryrc=.bigqueryrc --parameter='target_date:STRING:${{ steps.set_date.outputs.target_date }}' --format pretty < sql/sample-bq.sql | sed -z 's/\n/\\n/g')
          echo "result=$result" >> "$GITHUB_OUTPUT"

      - name: to slack
        uses: slackapi/slack-github-action@v1.23.0
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
        with:
          payload: |
            {
              "text": "```${{ steps.query.outputs.result }}```"
            }
  • sq/sample-bq.sql
#standardSQL
SELECT * FROM `sample.summary`
WHERE d > @target_date
ORDER BY d DESC

とりあえずサンプルっぽいテーブルからいくつかデータを取ってくるSQLを用意した

  • .bigqueryrc
[query]
--use_legacy_sql=false

SQL

bqコマンドで日付のパラメータを渡せるように@接頭辞をつけて@target_dateと記述している

渡す側(bqコマンド実行時のオプション)は--parameter='${パラメータ名}:${型}:${値}'と3つの値を:でつなげ、渡せるようにする

改行を含む結果を扱う

sed -zでNULL文字を区切り文字とし、\nを扱えるようにする(デフォルトは\nを区切り文字としているため直接置換などを行えない)

\をつけてエスケープする

Slack ActionのJSON payloadに改行は含められないので改行箇所をエスケープした1行のテキストを用意する

次のような感じになる

+------------+---------------+-----------+-------+----------+\n|     d      | iso_year_week | dayofweek | added | archived |\n+------------+-.......

Slack通知

slackapi/slack-github-action: Send data into Slack using this GitHub Action!

github.com

あらためて眺めてみたがこのActionはWorkflowBuilderのWebhookで使うのが推奨らしい…

個人では有料プランじゃないのと使えないためIncomingWebhookで通知する

Reference: Message payloads | Slack

api.slack.com

payloadのドキュメントを読む

出力される文字を等幅で表示したい(しないと表示が崩れてしまう)ためMarkdownのコードブロックを用いる

block kitを用いない場合はtextだけ指定すればOK(デフォルトでmrkdwnオプションが有効化されている)

出力はこんな感じ

終わり

block kitを使ってよしなにマッピングしてあげるのがつらいなということでこの手法を試してみた

長さによっては崩れてしまう(モバイルだとさらに許容される幅が少なくなる)がまぁこれはこれで良いでしょうという感じだった

どうしてもモバイルからもわかりやすく見れるようにしたい! という場合はblock kitでblocks以下をゴニョゴニョして面倒な整形をする必要がある

この辺もよしなにやれるようにしたいなーとは考えている