利用 Apps Script 讓 Google 表單成為自動化腳本的觸發點

Chengwei Chen
12 min readApr 25, 2021

(2021/12/25 註記:左思右想,決定棄用 Medium,未來更多文章請參閱 https://chengweichen.com

(本文的 Canonical URL — https://chengweichen.com/2021/04/apps-script-gitlab.html

最近看了一篇熱門文章《利用 Apps Script 讓 Google 表單回覆自動產出 Google 文件》,不看不知道,看了才知道原來 Google 有推出 Apps Script 這麼神奇好用的東西,透過它可以搭配 Google 的服務實現各種「辦公自動化」。

這麼有趣的服務,令人不禁想要天馬行空的運用它,究竟我們還可以拿 Apps Script 做什麼事情呢?

於是便想起前一陣子在研究 Jira service management 時注意到的一個功能 — — Customer Portal。簡單來說 Customer Portal 就是一個面向使用者的單一窗口與入口,假設今天是 IT/MIS 部門在使用 Jira service management,那麼 IT 部門就可以利用 Customer Portal 建立一個給一般員工使用的「IT 問題回報表單」。假如員工有各種 IT 問題,就填寫該表單,而 IT 部門會從 Jira service management 得到員工回報的問題資訊,根據資訊開立 Ticket 並分配給工程師處理。IT 部門除了可以從 Customer Portal 得到表單資訊之外,甚至可以設定如果填寫了表單的某些選項,就直接觸發對應事先準備好的自動化腳本,直接自動處理某些 IT 問題。

(Jira service management 的 Customer Portal。)

這麼棒的功能,真希望 GitLab 也能擁有,很可惜目前只能自己打造。所以就讓我們參考上面那篇文章,利用 Google 表單 + Apps Script + GitLab 來快速搭建一個陽春版的「IT 問題回報表單」。

陽春版的「IT 問題回報表單」希望可以做到三件事:

  1. 針對新發現的 IT 問題,能夠自動開立 GitLab Issue。
  2. 能用來重新啟動異常的服務(即是觸發 Service restart 的自動化腳本)
  3. 當有人填寫表單時,即送出通知至 Slack。

目標確立後,開始來動工吧!

操作步驟

首先我們需要一個 Google 表單。這部分應該不用特別教學吧?

總之我建立了一個有三個區塊的 Google 表單,第一個區塊用來控制欲回報的「問題類型」。

根據「問題類型」的選項,會分別前往區塊二「回報新的異常狀況」,或區塊三「服務需要重新啟動」。

表單建立後,也同步產生對應的 Google 試算表。

接著從 Google 試算表建立對應的 Apps Script。請選擇 工具 > 指令碼編輯器

接著 Google 會自動建立 Apps Script 並與試算表連結在一起。

下一步是重頭戲,撰寫我們所需的 Apps Script 程式碼。

function myFunction(event) {

// 取得 Google 試算表得到的資料
var formData = event.values;

// formData[0] 會是表單填寫的時間戳記
// formData[1] 開始才會是表單各欄位的資料

// 根據問題類型執行不同的動作
if (formData[1] == '回報新的異常狀況') {

// 問題類型 = 回報新的異常狀況 就根據表單內容開立 Issue
// 透過 GitLab API 來建立新 Issue
var url = 'https://gitlab.com/api/v4/projects/<your_gitlab_project_id>/issues?private_token=<your_gitlab_access_token>';

var payload = {
"title": 'New Issue - ' + formData[2] + ' (' + formData[0] + ')',
"description": formData[3],
};
}
else {

// 問題類型 = 服務需要重新啟動 就 trigger GitLab Runner 執行特定的自動化腳本
// 透過 GitLab API 來 Trigger GitLab CI Pipeline
var url = 'https://gitlab.com/api/v4/projects/<your_gitlab_project_id>/trigger/pipeline';

var payload = {
"token": "<your_gitlab_ci_trigger_token>",
"ref": "<your_git_branch>",
"variables": {'service_name': formData[4]},
};
}
Logger.log(payload);

var options = {
"method": "POST",
"contentType": "application/json",
"payload": JSON.stringify(payload)
};
Logger.log(options);

var response = UrlFetchApp.fetch(url, options);
Logger.log(response);

}

上面即是這次使用的範例程式,程式碼非常直白,一看就知道它會做幾件事:

  1. 取得這次 Google 表單送出的資料。
  2. 對應 Google 表單,formData[1] 會是「問題類型」,故依據這項資料進行 if else 判斷要去戳哪一個 GitLab API。
  3. 如果「問題類型」是「回報新的異常狀況」,就戳 Create New Issue 的 GitLab API。
  4. 如果「問題類型」是「服務需要重新啟動」,就用 GitLab API 去 Trigger 特定的 CI Pipeline。

上面程式碼有幾個地方要事先去 GitLab 那邊準備好。

  • <your_gitlab_project_id>,決定你會在哪一個 GitLab Project 建立 Issue,或是會 Trigger 哪一個 Project 的 CI Pipeline。
  • <your_gitlab_access_token>,GitLab API 需要 Access Token。
  • <your_gitlab_ci_trigger_token>,如果只是要 Trigger CI Pipeline,可以使用 Project > Settings > CI/CD > Pipeline triggers 這邊產生的 Token
  • <your_git_branch>,Trigger CI Pipeline 時,也要告知是哪一個 Branch 的 Pipeline。
(Pipeline triggers 可以產生 Trigger 專用的 Token。)

在 CI Pipeline 那邊,就隨需要撰寫了,由於本文只是簡單的 DEMO,我就只有驗證是否能順利取得 Variables。

# .gitlab-ci.yml

restart-service:
script:
- echo "即將重新啟動服務 - " $service_name

準備完畢,接著為 Apps Script 設置觸發條件,這裡就設定為「提交表單時」。

實際實驗一下成果。

填寫「回報新的異常狀況」,驗證是否會自動建立 Issue。

在 Apps Script 的「執行項目」中可以查看執行的狀況,由於我有設置 Logger,便會顯示 Log 資訊。

GitLab 也確實有增加一張新的 Issue。

填寫「服務需要重新啟動」,驗證是否有 Trigger CI Pipeline。

當然,Pipeline 成功運行,Variables 也有順利傳遞過來。

【補充說明】如果執行失敗,Apps script 的執行項目也會留下紀錄。

好了,實驗做完,本文就告一段落啦。等等,我們還有第三個目標「當有人填寫表單時,即送出通知至 Slack」沒有達成。

由於要實現「送出 Slack 通知」這件事的方法有很多種,這裡就不一一示範,僅用文字描述幾種可行的方案:

  1. 在 Apps Script 中透過 Post 將資料送至 Slack Webhook。
  2. 利用 GitLab 的 Project Integration,啟用 Slack notifications,並開啟 Issue、Pipeline 的 Notification。
  3. 如果是前述 Trigger CI Pipeline 的狀況,你也可以選擇在 CI Job 中 Post 資料送至 Slack Webhook。

至於我的規劃,我會選擇方案 1 + 2 + 3。(咦)

在 Apps Script 中設置兩種 Slack 訊息,第一是在 Google 表單已送出資料,但在 Apps Script 還沒有 POST 資料至任何 GitLab API 之前,先送出第一次的 Slack 訊息。這是用來通知對應窗口,有人填寫了表單。

假如新的 GitLab Issue 有順利建立,Apps Script 就根據 Response 中得到的 Issue ID,送出第二次的 Slack 訊息,在 Message 中會自動帶有 GitLab Issue 的 URL。如此方便對應窗口可以快速前往此 Issue。

接著也在 GitLab 的 Project Integration 中啟用 Slack notifications,但是只設置只有在 Pipeline 及 CI Job failed 時,才送出 Slack 訊息。如此一來倘若被 Trigger 的 Pipeline 其 CI Job 執行失敗,工程師就能立即收到通知,並接手處理異常狀況。

最後,讓 CI Job 除了執行自動化腳本外,最後一個動作則是送出 Slack 訊息。如此工程師也能藉此判斷被 Trigger 的 CI Pipeline 是否已成功執行完畢。

結語

我在以前的演講中也曾分享過,現在是一個充滿各種 API 的時代,透過程式與 API 的結合,讓我們能夠將越來越多的工作自動化。而本文即是利用 Google 表單 + Google Apps Script + GitLab 示範了其中一種可能性。

既然 Google Apps Script 可以用來 Trigger GitLab API,當然我們也能利用它做出更多有趣的事情,但唯獨要提醒大家注意「資安控管」的問題。就以本文的 DEMO 為例,確實我們實現了只要填寫 Google 表單,就能透過自動化去執行某個自動化腳本(本文假設的情境是 Restart service),可是不要忘了 Google 表單是沒有帳號權限控管的,也就是只要是知道該表單 URL 的人,都可隨意填寫。因此假如你真的打算依據本文的 DEMO 將 Google 表單作為自動化腳本的觸發點,那麼務必要確實思考如何做到「資安控管」,像是如何確保資料不是被亂填?以及填寫在 Apps Script 內的 Token 有沒有更好的保護機制⋯⋯。

最後,我個人認為 Google 表單 + Apps Script 是一個厲害的組合,或者應該說 Apps Script 本身即是一個厲害的服務。一樣以本文的 DEMO 為例,經過良好設計的表單是一種容易上手、幾乎不需要教育訓練人人皆會使用的工具,若是運用得宜,算是滿輕易的就能實現「任何人只要會填寫表單,即能自動完成工作」,更多的實現「辦公室自動化」、「工作自動化」。

寫到這裡,隱約之間好像想起了 MS 也有推出類似 Apps Script 的服務與工具,這樣看來現在果然是一個追求又懶又有生產力的時代,希望大家都能善用工具,將工作做的又自動、又快、又好。

工商服務

如果你覺得艦長寫的文章對你有產生幫助,歡迎抖內(Donate)艦長,讓艦長可以將原本用來養家活口的餘力分一些投入在社群分享上。咦,你說網頁上沒看到任何類似 Buy Me a Coffee 的連結?那不妨買一本艦長的著作《和艦長一起 30 天玩轉 GitLab》,不只能抖內艦長,還可以一併支持出版社與圖書通路商,一次抖內一舉數得喔!

參考資料

--

--

Chengwei Chen

暱稱:艦長,平日熱衷研究 DevOps、維運及自動化相關技術,目前為 GitLab Hero、DevOps Taiwan 社群志工。Medium 已停止更新,更多文章與個人經歷請參閱 https://chengweichen.com