コールバックと Google スプレッドシートを使用してワークフローを一時停止して再開する

Google スプレッドシートは、リアルタイムでの共同編集が可能な、データの可視化、処理、通信のためのツールを提供するクラウドベースのスプレッドシート ソリューションです。

このチュートリアルでは、コールバック エンドポイント(Webhook)を作成して、Google スプレッドシートにコールバック URL を保存し、実行を一時停止して、スプレッドシートの人間による承認を待機し、ワークフローを再起動するワークフローを作成してデプロイする方法を説明します。詳しくは、コールバックの使用方法をご覧ください。

Google ドライブで新しいフォルダを作成する

Google ドライブに新しいフォルダを作成します。このフォルダはスプレッドシートの保存に使用されます。共有フォルダの権限を設定することで、ワークフローによるスプレッドシートへの書き込みができるようになります。

  1. drive.google.com にアクセスする。
  2. [新規] > [新しいフォルダ] をクリックします。
  3. フォルダ名を入力します。
  4. [作成] をクリックします。
  5. 新しいフォルダを右クリックし、[共有] を選択します。
  6. Compute Engine のデフォルト サービス アカウントのメールアドレスを追加します。

    これにより、サービス アカウントにフォルダへのアクセスが許可されます。サービス アカウントをワークフローに関連付けると、そのワークフローにはフォルダ内の任意のファイルに対する編集権限が付与されます。ファイル、フォルダ、ドライブの共有の詳細

  7. 編集者のロールを選択します。

  8. [通知] チェックボックスをオフにします。

  9. [共有] をクリックします。

Google スプレッドシートを使用してスプレッドシートを作成する

Google スプレッドシートを使用して作成したスプレッドシートは、Google ドライブに保存されます。デフォルトでは、スプレッドシートはドライブのルートフォルダに保存されます。Google Sheets API を使用して、指定したフォルダ内に直接スプレッドシートを作成するオプションはありません。ただし、この例で示すように、スプレッドシートを作成した後に特定のフォルダに移動するなどの方法もあります。詳細については、Google ドライブ フォルダを操作するをご覧ください。

  1. sheets.google.com にアクセスします。

  2. [新規] をクリックします。Plus

    新しいスプレッドシートが作成され、開きます。各スプレッドシートには一意の spreadsheetId 値があり、これには文字、数字、ハイフン、アンダースコアが含まれます。スプレッドシート ID は Google スプレッドシートの URL で確認できます。

    https://docs.google.com/spreadsheets/d/spreadsheetId/edit#gid=0

  3. この ID はワークフローの作成時に必要になるため、メモしておいてください。

  4. 次の例と一致するように列見出しを追加します。

    承認を記録するスプレッドシートの例

    列 [G]、[Approved?] の値は、ワークフローでコールバックを開始するために使用されます。

  5. 前に作成した Google ドライブ フォルダにスプレッドシートを移動します。

    1. スプレッドシートで、[ファイル] > [移動] を選択します。
    2. 作成したフォルダに移動します。
    3. [移動] をクリックします。

また、Google Sheets API コネクタを使用してスプレッドシートを作成することもできます。コネクタを使用する場合、spreadsheetIdresp の結果から取得できます。次に例を示します。

- create_spreadsheet:
    call: googleapis.sheets.v4.spreadsheets.create
    args:
      body:
      connector_params:
        scopes: ${driveScope}
    result: resp
- assign_sheet_id:
    assign:
      - sheetId: ${resp.spreadsheetId}

Apps Script を使用して Google スプレッドシートを拡張する

Apps Script を使用すると、Google スプレッドシートの作成、読み取り、編集をプログラムで行うことができます。Google スプレッドシート用に設計されたほとんどのスクリプトでは、配列を操作してスプレッドシート内のセル、行、列を操作することができます。Google スプレッドシートで Apps Script を使用する方法については、カスタム関数のクイックスタートをご覧ください。

  1. Google スプレッドシートから Apps Script プロジェクトを作成する:

    1. Google スプレッドシートを開きます。
    2. [拡張機能] > [Apps Script] を選択します。
    3. スクリプト エディタで、[無題のプロジェクト] をクリックします。
    4. プロジェクトに名前を付けて、[名前を変更する] をクリックします。

    これで、スクリプトがスプレッドシートにバインドされます。これにより、スクリプトでユーザー インターフェースを変更したり、スプレッドシートを開いたときに応答したりできます。

    スクリプト プロジェクトは、Apps Script のファイルとリソースのコレクションを表します。スクリプト プロジェクトのコードファイルの拡張子は .gs です。

  2. Apps Script を使用すると、組み込み関数のように Google スプレッドシートで使用できるカスタム関数を作成できます。カスタム関数は、標準の JavaScript を使用して作成されます。関数を作成する

    1. Apps Script プロジェクトを開きます。
    2. [編集者] をクリックします。
    3. スクリプト ファイルは、Code.gs という名前のプロジェクト ファイルとして表示されます。ファイルを編集するには、そのファイルを選択します。
    4. スクリプト エディタのコードを次のコードに置き換えます。このコードは、スプレッドシート内のデータを読み取り、ワークフロー実行への入力として渡します。

      function handleEdit(e) {
        var range = e.range.getA1Notation();
        var sheet = e.source;
      
        if (range.length > 1 && range[0] === 'G') {
          if (e.value == "TRUE") {
            Logger.log("Approved: TRUE");
      
            var row = range.slice(1);
            var url = sheet.getRange('E' + row).getCell(1, 1).getValue();
            var approver = sheet.getRange('F' + row).getCell(1, 1).getValue();
      
            callback(url, approver);
          }
          else {
            Logger.log("Approved: FALSE");
          }
        }
      }
      
      function callback(url, approver) {
        const headers = {
          "Authorization": "Bearer " + ScriptApp.getOAuthToken()
        };
      
        var payload = {
          'approver': approver
        };
      
        const params = {
          "method": 'POST',
          "contentType": 'application/json',
          "headers": headers,
          "payload": JSON.stringify(payload)
        };
      
      
        Logger.log("Workflow callback request to " + url);
        var response = UrlFetchApp.fetch(url, params);
        Logger.log(response);
      }
    5. [保存] をクリックします。

  3. Apps Script のインストール可能なトリガーを使用すると、スプレッドシートを開いたり編集したりしたときなど、特定の条件が満たされたときに、スクリプト プロジェクトが指定された関数を実行できるようになります。トリガーを作成する

    1. Apps Script プロジェクトを開きます。
    2. [トリガー] をクリックします。
    3. [トリガーを追加] をクリックします。
    4. [YOUR_PROJECT_NAME のトリガーを追加] ダイアログで、トリガーを構成します。
      1. [実行する関数を選択] リストで、[handleEdit] を選択します。
      2. [実行するデプロイを選択] リストで、[Head] を選択します。
      3. [イベントソースを選択] リストで、[スプレッドシートから] を選択します。
      4. [イベントタイプを選択] リストで、[編集時] を選択します。
      5. [障害通知設定] リストで、[毎日通知] を選択します。
    5. [保存] をクリックします。
    6. Google アカウントを選択するように求められたら、適切なアカウントを選択して [許可] をクリックします。

      これにより、Apps Script プロジェクトが Google スプレッドシートのシートを表示、編集、作成、削除し、外部サービスに接続できるようになります。

  4. Apps Script プロジェクトのマニフェスト ファイルは、Apps Script がスクリプトを正常に実行するために必要な基本的なプロジェクト情報を指定する JSON ファイルです。Apps Script エディタでは、Apps Script プロジェクト設定を保護するため、デフォルトでマニフェスト ファイルが非表示になります。マニフェスト ファイルを編集します。

    1. Apps Script プロジェクトを開きます。
    2. [プロジェクトの設定] をクリックします。
    3. [「appsscript.json」マニフェスト ファイルをエディタで表示する] チェックボックスをオンにします。
    4. [編集者] をクリックします。
    5. マニフェスト ファイルは、appsscript.json という名前のプロジェクト ファイルとして表示されます。ファイルを編集するには、そのファイルを選択します。
    6. oauthScopes フィールドは、文字列の配列を指定します。プロジェクトで使用する認証スコープを設定するには、サポートするスコープを含む配列を追加します。次に例を示します。

      {
        "timeZone": "America/Toronto",
        "dependencies": {
        },
        "exceptionLogging": "STACKDRIVER",
        "runtimeVersion": "V8",
        "oauthScopes": [
          "https://www.googleapis.com/auth/script.external_request",
          "https://www.googleapis.com/auth/cloud-platform",
          "https://www.googleapis.com/auth/spreadsheets"
        ]
      }

      これにより、明示的なスコープが次のように設定されます。

      • 外部サービスへの接続
      • Google Cloud データの表示、編集、設定、削除、および Google アカウントのメールアドレスの表示
      • Google スプレッドシートのすべてのスプレッドシートの参照、編集、作成、削除
    7. [保存] をクリックします。

スプレッドシートに書き込み、コールバックを使用するワークフローをデプロイする

実行され、一時停止し、スプレッドシートでコールバックが承認されると再開するワークフローをデプロイします。ワークフローは、Google Sheets API コネクタを使用してスプレッドシートに書き込みます。

コンソール

  1. Google Cloud コンソールで、[ワークフロー] ページに移動します。

    [ワークフロー] に移動

  2. [ 作成] をクリックします。

  3. 新しいフィールドの名前を入力します: workflows-awaits-callback-sheets

  4. [リージョン] リストで [us-central1 (Iowa)] を選択します。

  5. [サービス アカウント] で、Compute Engine のデフォルトのサービス アカウント(PROJECT_NUMBER-compute@developer.gserviceaccount.com)を選択します。

  6. [次へ] をクリックします。

  7. ワークフロー エディタで、次のワークフローの定義を入力します。

    main:
      steps:
        - init:
            assign:
            # Replace with your sheetId and make sure the service account
            # for the workflow has write permissions to the sheet
            - sheetId: "10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"
        - before_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here before waiting for callback from sheets"}
        - wait_for_sheets_callback:
            call: await_callback_sheets
            args:
              sheetId: ${sheetId}
            result: await_callback_result
        - after_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here after receiving callback from sheets"}
        - returnResult:
            return: ${await_callback_result}
    
    await_callback_sheets:
        params: [sheetId]
        steps:
            - init:
                assign:
                  - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                  - location: ${sys.get_env("GOOGLE_CLOUD_LOCATION")}
                  - workflow_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}
                  - execution_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}
            - create_callback:
                call: events.create_callback_endpoint
                args:
                  http_callback_method: POST
                result: callback_details
            - save_callback_to_sheets:
                call: googleapis.sheets.v4.spreadsheets.values.append
                args:
                    range: ${"Sheet1!A1:G1"}
                    spreadsheetId: ${sheetId}
                    valueInputOption: RAW
                    body:
                        majorDimension: "ROWS"
                        values:
                          - ["${project_id}", "${location}", "${workflow_id}", "${execution_id}", "${callback_details.url}", "", "FALSE"]
            - log_and_await_callback:
                try:
                  steps:
                    - log_await_start:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Started waiting for callback from sheet " + sheetId}
                    - await_callback:
                        call: events.await_callback
                        args:
                          callback: ${callback_details}
                          timeout: 3600
                        result: callback_request
                    - log_await_stop:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Stopped waiting for callback from sheet " + sheetId}
                except:
                    as: e
                    steps:
                        - log_error:
                            call: sys.log
                            args:
                                severity: "ERROR"
                                text: ${"Received error " + e.message}
            - check_null_await_result:
                switch:
                  - condition: ${callback_request == null}
                    return: null
            - log_await_result:
                call: sys.log
                args:
                  severity: INFO
                  data: ${"Approved by " + callback_request.http_request.body.approver}
            - return_await_result:
                return: ${callback_request.http_request.body}
  8. プレースホルダ sheetId 値は spreadsheetId に置き換えてください。

  9. [デプロイ] をクリックします。

gcloud

  1. ワークフローのソースコード ファイルを作成します。

    touch workflows-awaits-callback-sheets.yaml
  2. テキスト エディタで、次のワークフローをソースコード ファイルにコピーします。

    main:
      steps:
        - init:
            assign:
            # Replace with your sheetId and make sure the service account
            # for the workflow has write permissions to the sheet
            - sheetId: "10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"
        - before_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here before waiting for callback from sheets"}
        - wait_for_sheets_callback:
            call: await_callback_sheets
            args:
              sheetId: ${sheetId}
            result: await_callback_result
        - after_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here after receiving callback from sheets"}
        - returnResult:
            return: ${await_callback_result}
    
    await_callback_sheets:
        params: [sheetId]
        steps:
            - init:
                assign:
                  - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                  - location: ${sys.get_env("GOOGLE_CLOUD_LOCATION")}
                  - workflow_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}
                  - execution_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}
            - create_callback:
                call: events.create_callback_endpoint
                args:
                  http_callback_method: POST
                result: callback_details
            - save_callback_to_sheets:
                call: googleapis.sheets.v4.spreadsheets.values.append
                args:
                    range: ${"Sheet1!A1:G1"}
                    spreadsheetId: ${sheetId}
                    valueInputOption: RAW
                    body:
                        majorDimension: "ROWS"
                        values:
                          - ["${project_id}", "${location}", "${workflow_id}", "${execution_id}", "${callback_details.url}", "", "FALSE"]
            - log_and_await_callback:
                try:
                  steps:
                    - log_await_start:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Started waiting for callback from sheet " + sheetId}
                    - await_callback:
                        call: events.await_callback
                        args:
                          callback: ${callback_details}
                          timeout: 3600
                        result: callback_request
                    - log_await_stop:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Stopped waiting for callback from sheet " + sheetId}
                except:
                    as: e
                    steps:
                        - log_error:
                            call: sys.log
                            args:
                                severity: "ERROR"
                                text: ${"Received error " + e.message}
            - check_null_await_result:
                switch:
                  - condition: ${callback_request == null}
                    return: null
            - log_await_result:
                call: sys.log
                args:
                  severity: INFO
                  data: ${"Approved by " + callback_request.http_request.body.approver}
            - return_await_result:
                return: ${callback_request.http_request.body}
  3. プレースホルダ sheetId 値は spreadsheetId に置き換えてください。

  4. 次のコマンドを入力してワークフローをデプロイします。

    gcloud workflows deploy workflows-awaits-callback-sheets \
        --source=workflows-awaits-callback-sheets.yaml \
        --location=us-central1 \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com

    PROJECT_NUMBER は、使用する Google Cloudプロジェクト番号に置き換えます。プロジェクト番号を取得します。

    gcloud projects describe PROJECT_ID

エンドツーエンドのフローをテストする

ワークフローを実行して、エンドツーエンドのフローをテストします。ワークフローを実行すると、そのワークフローに関連付けられた現在のワークフロー定義が実行されます。

コンソール

  1. Google Cloud コンソールで、[ワークフロー] ページに移動します。

    [ワークフロー] に移動

  2. [Workflows] ページで、[workflows-awaits-callback-sheets] ワークフローを選択して詳細ページに移動します。

  3. [ワークフローの詳細] ページで [ 実行] を選択します。

  4. もう一度 [Execute] をクリックします。

    ワークフローが開始され、実行状態が [実行中] になります。ログには、ワークフローが一時停止して待機していることも示されます。

    Execute steps here before waiting for callback from sheets
    ...
    Started waiting for callback from sheet 1JlNFFnqs760M_KDqeeeDc_qtrABZDxoalyCmRE39dpM
  5. ワークフローによって、スプレッドシートの行にコールバックの詳細が書き込まれていることを確認します。

    たとえば、ワークフローの実行 ID は実行 ID 列、コールバック エンドポイントはコールバック URL 列、FALSE承認済みですか?列に表示されます。

  6. スプレッドシートで、FALSETRUE に変更します。

    1~2 分後に実行が再開され、実行ステータスが [Succeeded] になり完了します。

gcloud

  1. ターミナルを開きます。

  2. ワークフローを実行します。

      gcloud workflows run workflows-awaits-callback-sheets

    ワークフローが開始され、ワークフローが一時停止して待機していることが出力に表示されます。

      Waiting for execution [a8361789-90e0-467f-8bd7-ea1c81977820] to complete...working.

  3. ワークフローによって、スプレッドシートの行にコールバックの詳細が書き込まれていることを確認します。

    たとえば、ワークフローの実行 ID は実行 ID 列、コールバック エンドポイントはコールバック URL 列、FALSE承認済みですか?列に表示されます。

  4. スプレッドシートで、FALSETRUE に変更します。

    1~2 分後に実行が再開され、実行ステータスが SUCCEEDED になります。