ejangi
ejangi

Reputation: 3

How to deploy a Google Cloud Function using Google Cloud Build with substitutions

I am trying to deploy a Google Cloud Function using Google Cloud Build (including substitutions).

However, I am receiving the error when it builds:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function failed on loading user code. Error message: Provided module can't be loaded.
Detailed stack trace: Error: Incoming webhook URL is required

My cloudbuild.yaml file contains:

steps:

# This step builds the container image.
- name: 'gcr.io/cloud-builders/gcloud'
  id: Deploy
  args: ['functions', 'deploy', 'subscribeSlack', '--trigger-topic', 'cloud-builds', '--runtime', 'nodejs10', '--set-env-vars', '"SLACK_WEBHOOK_URL=${_SLACK_WEBHOOK_URL}"', '--region', '${_REGION}']
  env: 
    - 'SLACK_WEBHOOK_URL=${_SLACK_WEBHOOK_URL}'

And, I have added the substitutions in the trigger via Google Cloud Console: screenshot of build trigger with substitutions filled in.

The function itself is based on the example from Google's documentation:

const { IncomingWebhook } = require('@slack/webhook');
const url = process.env.SLACK_WEBHOOK_URL;

const webhook = new IncomingWebhook(url);

// subscribeSlack is the main function called by Cloud Functions.
module.exports.subscribeSlack = (pubSubEvent, context) => {
  const build = eventToBuild(pubSubEvent.data);

  // Skip if the current status is not in the status list.
  // Add additional statuses to list if you'd like:
  // QUEUED, WORKING, SUCCESS, FAILURE,
  // INTERNAL_ERROR, TIMEOUT, CANCELLED
  const status = ['SUCCESS', 'FAILURE', 'INTERNAL_ERROR', 'TIMEOUT'];
  if (status.indexOf(build.status) === -1) {
    return;
  }

  // Send message to Slack.
  const message = createSlackMessage(build);
  webhook.send(message);
};

// eventToBuild transforms pubsub event message to a build object.
const eventToBuild = (data) => {
  return JSON.parse(Buffer.from(data, 'base64').toString());
}

// createSlackMessage creates a message from a build object.
const createSlackMessage = (build) => {
  console.log(JSON.stringify(build));
  const message = {
    text: `Build \`${build.status}\``,
    mrkdwn: true,
    attachments: [
      {
        title: 'Build logs',
        title_link: build.logUrl,
        fields: [{
          title: 'Status',
          value: build.status
        }]
      }
    ]
  };

  if(build.source.repoSource.repoName !== undefined)
    message.attachments[0].fields.push({ title: "Repo", value: build.source.repoSource.repoName });

  if(build.finishTime !== undefined)
    message.attachments[0].fields.push({ title: "Finished", value: (new Date(build.finishTime)).toLocaleString('en-GB', {timeZone: "Australia/Brisbane"}) });

  return message;
}

The function deploys fine from the gcloud cli, but only fails when using Cloud Build.

Upvotes: 0

Views: 600

Answers (1)

Soni Sol
Soni Sol

Reputation: 2612

I checked the cloudbuild.yaml and I found that having double and single quotes around SLACK_WEBHOOK_URL=${_SLACK_WEBHOOK_URL} generates this issue, taking out the double quotes seems to solve it.

I attach the modified cloudbuild.yaml

steps:
# This step builds the container image.
- name: 'gcr.io/cloud-builders/gcloud'
  id: Deploy
  args: ['functions', 'deploy', 'subscribeSlack', '--trigger-topic', 'cloud-builds', '--runtime', 'nodejs10', '--set-env-vars', 'SLACK_WEBHOOK_URL=${_SLACK_WEBHOOK_URL}', '--region', '${_REGION}']
  env:
    - 'SLACK_WEBHOOK_URL=${_SLACK_WEBHOOK_URL}'

Upvotes: 1

Related Questions