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


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

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

目標

このチュートリアルの内容は次のとおりです。

  1. Google ドライブに新しいフォルダを作成します。このフォルダは、スプレッドシートの保存に使用されます。これにより、ワークフローによるスプレッドシートへの書き込みが可能になります。
  2. Google スプレッドシートを作成して承認を取得し、ワークフローに対するコールバックを開始します。
  3. クラウドベースの JavaScript プラットフォームである Google Apps Script を使用して、Google Workspace プロダクトをプログラムで作成、読み取り、編集し、一時停止したワークフローの再開をスプレッドシートの更新を通してリクエストが承認されるたびにワークフローをトリガーします。
  4. Google Sheets API コネクタを呼び出してデータをスプレッドシートに追加するワークフローを作成してデプロイします。ワークフローが実行され、一時停止し、スプレッドシートでコールバックが承認されると再開します。Workflows コネクタの詳細を確認する
  5. プロセス全体をテストして、ワークフローが想定どおりに進行することを確認します。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このチュートリアルでは、Google Workspace も使用します。Google の無料の一般ユーザー向けアプリに含まれていないビジネス レベルのサービスは、課金対象になります。

始める前に

Google Cloud コンソールで次のコマンドを実行するか、ターミナルまたは Cloud Shell で Google Cloud CLI を使用できます。

組織で定義されているセキュリティの制約により、次の手順を完了できない場合があります。トラブルシューティング情報については、制約のある Google Cloud 環境でアプリケーションを開発するをご覧ください。

コンソール

  1. Google Cloud コンソールのプロジェクト セレクタ ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  2. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  3. Compute Engine、Google スプレッドシート、Workflows API を有効にします。

    API を有効にする

  4. Compute Engine のデフォルトのサービス アカウントをメモしておきます。テスト目的で、このチュートリアルのワークフローに関連付けるためです。Compute Engine API が有効になっている新しいプロジェクトには、IAM 基本編集者ロールや、以下のメール形式を持つサービス アカウントが作成されます。

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    プロジェクト番号は、Google Cloud コンソールの [ようこそ] ページで確認できます。

    本番環境では、新しいサービス アカウントを作成して、必要最小限のアクセス許可を含む、最小権限の原則に従った 1 つ以上の IAM ロールを付与することを強くおすすめします。

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Google Cloud プロジェクトの課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  3. Compute Engine、Google スプレッドシート、Workflows API を有効にします。

    gcloud services enable \
        compute.googleapis.com \
        sheets.googleapis.com \
        workflows.googleapis.com
  4. Compute Engine のデフォルトのサービス アカウントをメモしておきます。テスト目的で、このチュートリアルのワークフローに関連付けるためです。Compute Engine API が有効になっている新しいプロジェクトには、IAM 基本編集者ロールや、以下のメール形式を持つサービス アカウントが作成されます。

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    プロジェクト番号を取得します。

    gcloud projects describe PROJECT_ID

    本番環境では、新しいサービス アカウントを作成して、必要最小限のアクセス許可を含む、最小権限の原則に従った 1 つ以上の IAM ロールを付与することを強くおすすめします。

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 コネクタを使用してスプレッドシートに書き込みます。

Console

  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

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

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

Console

  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 になります。

クリーンアップ

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。

プロジェクトを削除する

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

このチュートリアルで作成したリソースを削除する

  1. Google ドライブ内のファイルを削除する
  2. ワークフローを削除する

次のステップ