Pause e retome um fluxo de trabalho através de callbacks e do Google Sheets

O Google Sheets é uma solução de folha de cálculo baseada na nuvem que suporta a colaboração em tempo real e oferece ferramentas para visualizar, processar e comunicar dados.

Este tutorial demonstra como criar e implementar um fluxo de trabalho que cria um ponto final de retorno de chamada (ou webhook), guarda o URL de retorno de chamada no Google Sheets, pausa a execução e, em seguida, aguarda a aprovação humana através da folha de cálculo do Sheets para reiniciar o fluxo de trabalho. Saiba mais sobre a utilização de retornos de chamada.

Crie uma nova pasta no Google Drive

Crie uma nova pasta no Google Drive. Esta pasta é usada para armazenar a sua folha de cálculo. Ao configurar uma autorização para a pasta partilhada, o seu fluxo de trabalho tem permissão para escrever na folha de cálculo.

  1. Aceda a drive.google.com.
  2. Clique em Novo > Nova pasta.
  3. Introduza um nome para a pasta.
  4. Clique em Criar.
  5. Clique com o botão direito do rato na nova pasta e selecione Partilhar.
  6. Adicione o endereço de email da conta de serviço predefinida do Compute Engine.

    Isto concede à conta de serviço acesso à pasta. Quando associa a conta de serviço ao seu fluxo de trabalho, o fluxo de trabalho tem acesso de edição a qualquer ficheiro na pasta. Saiba mais sobre a partilha de ficheiros, pastas e discos.

  7. Selecione a função Editor.

  8. Desmarque a caixa de verificação Notificar pessoas.

  9. Clique em Partilhar.

Crie uma folha de cálculo com o Google Sheets

Quando cria uma folha de cálculo através do Google Sheets, esta é guardada no Google Drive. Por predefinição, a folha de cálculo é guardada na pasta raiz do Drive. Não existe uma opção para criar uma folha de cálculo diretamente numa pasta especificada através da API Google Sheets. No entanto, existem alternativas, incluindo mover a folha de cálculo para uma pasta específica depois de a criar, como é feito neste exemplo. Para mais informações, consulte o artigo Trabalhe com pastas do Google Drive.

  1. Aceda a sheets.google.com.

  2. Clique em Novo Plus.

    Isto cria e abre a sua nova folha de cálculo. Cada folha de cálculo tem um valor spreadsheetId exclusivo, com letras, números, hífenes ou sublinhados. Pode encontrar o ID da folha de cálculo num URL do Google Sheets:

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

  3. Tome nota deste ID, pois vai precisar dele quando criar o fluxo de trabalho.

  4. Adicione cabeçalhos de colunas de acordo com o seguinte exemplo:

    Exemplo de folha de cálculo para registar aprovações

    Tenha em atenção que o valor na coluna G, Aprovado?, é usado para iniciar callbacks no fluxo de trabalho.

  5. Mova a folha de cálculo para a pasta do Google Drive que criou anteriormente:

    1. Na folha de cálculo, selecione Ficheiro > Mover.
    2. Navegue até à pasta que criou.
    3. Clique em Mover.

Também pode usar o conetor da API Google Sheets para criar uma folha de cálculo. Tenha em atenção que, quando usa o conector, o elemento spreadsheetId pode ser obtido a partir do resultado resp. Por exemplo:

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

Expanda o Google Sheets com o Apps Script

O Apps Script permite-lhe criar, ler e editar o Google Sheets de forma programática. A maioria dos scripts concebidos para o Sheets manipulam matrizes para interagir com as células, as linhas e as colunas numa folha de cálculo. Para uma introdução à utilização do Apps Script com o Google Sheets, consulte o Início rápido de funções personalizadas.

  1. Crie um projeto do Apps Script a partir do Google Sheets:

    1. Abra a folha de cálculo do Sheets.
    2. Selecione Extensões > Apps Script.
    3. No editor de scripts, clique em Projeto sem título.
    4. Atribua um nome ao projeto e clique em Mudar o nome.

    O script está agora associado à sua folha de cálculo, o que confere ao script capacidades especiais para alterar a interface do utilizador ou responder quando a folha de cálculo é aberta.

    Um projeto de script representa uma coleção de ficheiros e recursos do Apps Script. Os ficheiros de código num projeto de script têm uma extensão..gs

  2. Pode usar o Apps Script para escrever funções personalizadas que pode usar no Google Sheets tal como uma função incorporada. As funções personalizadas são criadas com JavaScript padrão. Crie uma função:

    1. Abra o seu projeto do Apps Script.
    2. Clique em Editor .
    3. Um ficheiro de script é apresentado como um ficheiro de projeto com o nome Code.gs. Para editar o ficheiro, selecione-o.
    4. Substitua qualquer código no editor de scripts pelo seguinte código que lê os dados na sua folha de cálculo e transmite-os como entrada para uma execução do fluxo de trabalho:

      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. Clique em Guardar .

  3. Os acionadores instaláveis do Apps Script permitem que um projeto de script execute uma função especificada quando determinadas condições são cumpridas, como quando uma folha de cálculo é aberta ou editada. Crie um acionador:

    1. Abra o seu projeto do Apps Script.
    2. Clique em Acionadores .
    3. Clique em Adicionar acionador.
    4. Na caixa de diálogo Adicionar acionador para YOUR_PROJECT_NAME, configure o acionador:
      1. Na lista Escolha a função a executar, selecione handleEdit.
      2. Na lista Escolha a implementação que deve ser executada, selecione Principal.
      3. Na lista Selecionar origem do evento, selecione Da folha de cálculo.
      4. Na lista Selecionar tipo de evento, selecione Na edição.
      5. Na lista Definições de notificação de falhas, selecione Notificar-me diariamente.
    5. Clique em Guardar.
    6. Se receber um pedido para escolher uma Conta Google, selecione a conta adequada e, de seguida, clique em Permitir.

      Isto permite que o seu projeto do Apps Script veja, edite, crie e elimine as suas folhas de cálculo do Google Sheets, bem como se ligue a um serviço externo.

  4. Um ficheiro de manifesto de um projeto do Apps Script é um ficheiro JSON que especifica informações básicas do projeto que o Apps Script precisa para executar um script com êxito. Tenha em atenção que o editor do Apps Script oculta os ficheiros de manifesto por predefinição para proteger as definições do seu projeto do Apps Script. Edite o ficheiro de manifesto:

    1. Abra o seu projeto do Apps Script.
    2. Clique em Definições do projeto .
    3. Selecione a caixa de verificação Mostrar ficheiro de manifesto "appsscript.json" no editor.
    4. Clique em Editor .
    5. O ficheiro de manifesto aparece como um ficheiro de projeto com o nome appsscript.json. Para editar o ficheiro, selecione-o.
    6. O campo oauthScopes especifica uma matriz de strings. Para definir os âmbitos de autorização que o seu projeto usa, adicione uma matriz com os âmbitos que quer suportados. Por exemplo:

      {
        "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"
        ]
      }

      Isto define âmbitos explícitos para:

      • Ligar a um serviço externo
      • Ver, editar, configurar e eliminar os seus Google Cloud dados e ver o endereço de email da sua Conta Google
      • Ver, editar, criar e eliminar todas as suas folhas de cálculo do Google Sheets
    7. Clique em Guardar .

Implemente um fluxo de trabalho que escreve numa folha de cálculo e usa callbacks

Implemente um fluxo de trabalho que é executado, pausado e, em seguida, retomado quando um retorno de chamada é aprovado através de uma folha de cálculo. O fluxo de trabalho escreve numa folha de cálculo do Sheets através do conetor da API Google Sheets.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Clique em Criar.

  3. Introduza um nome para o novo fluxo de trabalho: workflows-awaits-callback-sheets.

  4. Na lista Região, selecione us-central1 (Iowa).

  5. Para a Conta de serviço, selecione a conta de serviço predefinida do Compute Engine (PROJECT_NUMBER-compute@developer.gserviceaccount.com).

  6. Clicar em Seguinte.

  7. No editor de fluxos de trabalho, introduza a seguinte definição para o seu fluxo de trabalho:

    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. Certifique-se de que substitui o valor do marcador de posição sheetId pelo seu spreadsheetId.

  9. Clique em Implementar.

gcloud

  1. Crie um ficheiro de código-fonte para o seu fluxo de trabalho:

    touch workflows-awaits-callback-sheets.yaml
  2. Num editor de texto, copie o seguinte fluxo de trabalho para o ficheiro de código-fonte:

    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. Certifique-se de que substitui o valor do marcador de posição sheetId pelo seu spreadsheetId.

  4. Implemente o fluxo de trabalho introduzindo o seguinte comando:

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

    Substitua PROJECT_NUMBER pelo seu Google Cloud número do projeto. Pode obter o número do projeto:

    gcloud projects describe PROJECT_ID

Teste o fluxo integral

Execute o fluxo de trabalho para testar o fluxo integral. A execução de um fluxo de trabalho executa a definição do fluxo de trabalho atual associada ao fluxo de trabalho.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Na página Fluxos de trabalho, selecione o fluxo de trabalho workflows-awaits-callback-sheets para aceder à respetiva página de detalhes.

  3. Na página Detalhes do fluxo de trabalho, clique em Executar.

  4. Clique novamente em Executar.

    O fluxo de trabalho é iniciado e o respetivo estado de execução deve ser Em execução. Os registos também indicam que o fluxo de trabalho está em pausa e a aguardar:

    Execute steps here before waiting for callback from sheets
    ...
    Started waiting for callback from sheet 1JlNFFnqs760M_KDqeeeDc_qtrABZDxoalyCmRE39dpM
  5. Verifique se o fluxo de trabalho escreveu os detalhes da chamada de retorno numa linha da sua folha de cálculo.

    Por exemplo, deve ver o ID de execução do fluxo de trabalho na coluna ID de execução, um ponto final de retorno de chamada na coluna URL de retorno de chamada e FALSE na coluna Aprovado?.

  6. Na folha de cálculo, altere o valor FALSO para VERDADEIRO.

    Após um ou dois minutos, a execução deve ser retomada e, em seguida, concluída com um estado de execução de Succeeded.

gcloud

  1. Abra um terminal.

  2. Execute o fluxo de trabalho:

      gcloud workflows run workflows-awaits-callback-sheets

    O fluxo de trabalho é iniciado e o resultado deve indicar que o fluxo de trabalho está em pausa e a aguardar:

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

  3. Verifique se o fluxo de trabalho escreveu os detalhes da chamada de retorno numa linha da sua folha de cálculo.

    Por exemplo, deve ver o ID de execução do fluxo de trabalho na coluna ID de execução, um ponto final de retorno de chamada na coluna URL de retorno de chamada e FALSE na coluna Aprovado?.

  4. Na folha de cálculo, altere o valor FALSO para VERDADEIRO.

    Após um ou dois minutos, a execução deve ser retomada e, em seguida, concluída com um estado de execução de SUCCEEDED.