GitHub Actions のワークフローを開始する Google Drive のアドオン
dispatch workflow の input を使ったら Google Drive のファイルを簡単にワークフローに渡せると思ったので。試してみた。
アドオンの利用
もともとは Google Apps Script で Documents などのメニューにワークフロー開始コマンドを追加するつもりだったが、Makrdown ファイルだとできなさそう。
ドライブのコンテキストメニュー的なところに項目を追加できないかと調べてみたらアドオンを作るとサイドパネルが使えるもよう。
少し試してみたら Documents などの Google のアプリでなくてもファイルの id などが取得できたのでここれを利用する。
Google Drive 用のアドオンは以下が参考になった。
ファイルの構成、デプロイ(非公開のテスト用)の方法はクイックスタートが参考になる。
Input の内容を表示させない
入力の内容によってはログに表示させたくはない。
明確な方法は見つからなかったがイベントはファイルに保存されているので、そこから切り出すと表示されないようできた(と思う)。
とりあえずファイルの保存をするだけなので、以下のようにしてある。::add-mask
も問題ないと思われる。
on:
workflow_dispatch:
inputs:
slides:
type: string
required: true
description: Slide source
steps:
- uses: actions/checkout@v3
- name: Parse event
id: parse
run: cat "${GITHUB_EVENT_PATH}" | jq -r .inputs.slides > slides.md
とりあえずの実装
実装して気が付いたところ。
ソースファイルの更新
-
clasp push
の後、ドライブのウェブ UI をリロードすると更新は反映される- デプロイのやりなおしは不要
-
appscript.json
の更新も同様
UI 的なところ
- ボタンクリックで post などを行っているときはスピナーが表示される
- Card を切り替えるとファイルを選択しなおしてもそのまま
- 画面遷移をつめる必要がある
入力は
- 複数行の入力も普通に扱える(ワークフローコマンド用の改行のエンコード的なものはなかった)
- サイズ制限は不明(環境変数の大きさに左右されそうかな)
あとは
- ワークフローの実行状況の確認
- 複数同時に開始されたときに前のワークフローをキャンセル
- ファイル ID が同じものに限定できる?
あたりは実施したい。
複数同時実行されたときの先行ワークフローのキャンセルについて。
並行処理グループには、任意の文字列または式を使用できます。 式は、
secrets
コンテキストを除く任意のコンテキストを使用できます。
https://docs.github.com/ja/actions/using-jobs/using-concurrency
file_id でグループ化したかったが、外部に出したくない情報でのグループ化は避けた方が無難なもよう。
対策としては secrets
に salt 的なものを登録してハッシュ化するとか。
あるいは、割り切って全体で 1 つだけにするか。
concurrency.group
の内容はキャンセルされた時に Annotations で表示される。
ANNOTATIONS
X Canceling since a higher priority waiting request for 'xxxxxxx' exists
add-mask
が効かないかは試してない。
どちらにしろ危ないのでとりあえずハッシュ化用の処理を追加。
steps:
- name: Parse event
id: parse
run: |
echo -n '::set-output name=group_key::' > cmd_out.txt
envsubst < <(echo "$SALT") > key.txt
jq < "${GITHUB_EVENT_PATH}" -r .inputs.file_id >> key.txt
sha256sum < key.txt >> cmd_out.txt
cat cmd_out.txt
rm cmd_out.txt
env:
SALT: ${{ secrets.SALT }}
が、ハッシュ化の処理を記述した後に addon 側から正直 file_id
を送信しなくてもよいことに気が付いた。addon 側で処理した方が楽だったかな。
addon のローカライズ
標準的な方法はない?
検索すると以下が定番ぽい。
とりあえず。
type MsgKey_ =
| 'SELECT_MARKDOWN_FILE'
| 'NOT_SUPPORT_TYPE'
| 'NOT_SUPPORT_MULTIPLE_SELECT'
| 'ERR_WORKFLOW_NOT_STARTED'
const msgTbl_: Record<MsgKey_, Record<string, string>> = {
SELECT_MARKDOWN_FILE: {
ja: 'Markdown ファイルを選択してください。'
},
NOT_SUPPORT_TYPE: {
ja: 'ファイルタイプは text/markdown のみサポートされています。'
},
NOT_SUPPORT_MULTIPLE_SELECT: {
ja: '複数ファイルの選択はサポートされていません。'
},
ERR_WORKFLOW_NOT_STARTED: {
ja: 'ワークフロー開始時にエラーが発生しました。'
}
}
const msgLocale_ = Session.getActiveUserLocale()
function msgText_(key: keyof typeof msgTbl_): string {
const msg = msgTbl_[key]
if (typeof msg === 'object') {
if (typeof msg[msgLocale_] === 'string') {
return msg[msgLocale_]
}
if (typeof msg['ja'] === 'string') {
return msg['ja']
}
}
throw new Error(`Ivalid key: ${key} ${msgLocale_}`)
}
addon での入力
ユーザー入力のイベントの構造が実際の値とドキュメントの記述で異なる。
(型の定義はドキュメントと同じ)
少し検索したところ、以下が出てきた。変更があったということでよいのか?
Spoke to a colleague who figured out that the [""] is no longer needed. This is what works instead:
関数にした。
function getSelectionInputValue_(
e: GoogleAppsScript.Addons.EventObject,
fieldName: string
): string[] {
const targetValue =
e.commonEventObject.formInputs?.[fieldName] !== undefined
? (e.commonEventObject.formInputs[fieldName] as any)
: undefined
if (targetValue) {
if (targetValue['']) {
return targetValue[''].stringInputs.value
}
return targetValue.stringInputs.value
}
return []
}