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

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

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

(本文同步發佈於 Medium。)

如前面所述,在思考 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。) (Jira service management 的 Customer Portal。)

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

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

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

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

操作步驟

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

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

(Google 表單)

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

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

Google 試算表

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

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。) (Pipeline triggers 可以產生 Trigger 專用的 Token。)

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

# .gitlab-ci.yml

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

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

Apps Script

實際實驗一下成果。

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

Google 表單

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

Apps Script Logs

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

GitLab Issue

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

Google 表單

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

GitLab CI Log

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

好了,實驗做完,本文就告一段落啦。等等,我們還有第三個目標「當有人填寫表單時,即送出通知至 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 Pipeline 的異常狀況。

最後,讓 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 的服務與工具,這樣看來現在果然是一個追求又懶又有生產力的時代,希望大家都能善用工具,將工作做的又自動、又快、又好。

參考資料

轉貼本文時禁止修改,禁止商業使用,並且必須註明來自「艦長,你有事嗎?」原創作者 Cheng Wei Chen,及附上原文連結。

工商服務

更多文章