slackapi / bolt-js

A framework to build Slack apps using JavaScript
https://tools.slack.dev/bolt-js/
MIT License
2.74k stars 393 forks source link

Can't get deploy my app as a google cloud function. ('app' needs to be of type function. Got: object) #1715

Closed ChristopheFlimo closed 1 year ago

ChristopheFlimo commented 1 year ago

Description

Has anyone been able to deploy to Google cloud function? Google cloud require the parameter --entry-point and it needs to be a function.

if I export my bolt app: exports.app = app

and run gcloud functions deploy slack --runtime nodejs16 --trigger-http --entry-point app

I get the following error from google cloud:

'app' needs to be of type function. Got: object

ChatGPT has been trying to solve the issue but it's also not working.

const { App } = require("@slack/bolt");

const dotenv = require('dotenv');
dotenv.config();

const app = new App({

token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});

exports.slackBot = app.requestHandler;

I get then the following error: Function 'slackBot' is not defined in the provided module.

What type of issue is this? (place an x in one of the [ ])

Requirements (place an x in each of the [ ])

seratch commented 1 year ago

Hi @ChristopheFlimo, thanks for asking the question! It seems that your way is not a valid way to provide a handler for Cloud Functions. Please refer to https://github.com/slackapi/bolt-js/issues/213 to learn the right ways for it. I hope this was helpful to you!

ChristopheFlimo commented 1 year ago

@seratch , thank for your help. I have looked at your example and I have added the follwing to my cloud function:

const { App, ExpressReceiver } = require('@slack/bolt');
const expressReceiver = new ExpressReceiver({
  signingSecret: config.SLACK_SIGNING_SECRET
});
const app = new App({
  token: config.SLACK_BOT_TOKEN,
  receiver: expressReceiver
});
const expressApp = expressReceiver.app;

And

function isOnGoogleCloud() {
  // https://cloud.google.com/functions/docs/env-var#nodejs_10_and_subsequent_runtimes
  return process.env.K_SERVICE && process.env.K_REVISION;
}

if (!isOnGoogleCloud()) {
  // Running on your local machine
  (async () => {
    // Start your app
    expressApp.listen(config.SLACK_APP_PORT || 3000);
    console.log('⚡️ Slack app is running!');
  })();
}

module.exports.app = function (req, res) {
  console.log(`Got a request: ${JSON.stringify(req.headers)}`);
 console.log(`Got path: ${req.path}`);
  if (req.rawBody) {
    console.log(`Got raw request: ${req.rawBody}`)

  }
  expressApp(req, res);
};

I however keep getting 404.

Got a request: .... Got raw request: .... Go path: /events "Function execution took 7 ms, finished with status code: 404"

Strangely outputing the path give me "/events" Not [name of my cloud function]/ events Is that normal

Also, I have not added the following. I am not sure how to find my SLACK_API_TOKEN

// ------------------------------------------------------
// If you need to use API methods that are not listed on https://api.slack.com/bot-users#methods
// you need to use user api token instead like this:
const { WebClient } = require('@slack/web-api');
app.client = new WebClient(config.SLACK_API_TOKEN);
seratch commented 1 year ago

Strangely outputing the path give me "/events" Not [name of my cloud function]/ events Is that normal

Can you double-check the Request URL in your https://api.slack.com/apps configuration page? Perhaps, the URL may have the suffix "/events"

ChristopheFlimo commented 1 year ago

thanks for getting back so fast @seratch my request URL is https://************.cloudfunctions.net/slack/events

ChristopheFlimo commented 1 year ago

And on the page I get : 'Request URL Your URL didn't respond with the value of the challenge parameter'. The Cloud function log log show a request was made. but again with a 404 response.

seratch commented 1 year ago

When you run a bolt-js app on Cloud Functions, the URL cannot be "/slack/events" path. The path should be just your function's name.

ChristopheFlimo commented 1 year ago

I changed to https://************.cloudfunctions.net/slack I still get 'Request URL Your URL didn't respond with the value of the challenge parameter'.

The cloud function log is : Got a Path: "/" Function execution took 9 ms, finished with status code: 404

seratch commented 1 year ago

When you use the ExpressReceiver, it seems that you need to add endpoints: '/events' to the initialization args. See https://github.com/slackapi/bolt-js/issues/213#issuecomment-510403498 for more details.

ChristopheFlimo commented 1 year ago

Thanks a lot @seratch! It seems that I can now call my cloud function with endpoints: '/events' However, I am running into massive performance issues now. Calls that use to take less than a seconds on my local dev environment (local node server and stunel.io to my machine) are now taking several minutes using cloud function. Those events create or update firestone records and aren't particularly optimised so 1 or 2 secs would be ok but not minutes. Have you experience this type of issues? I was thinking maybe app engine might work better, or would you recommend something else ? (I am not really good with devops stuff) My only concern is that I have started using firestore since development to only use one cloud provider if possible. So staying with google would be great. But my ultimate goal is to get my slack app to early users as soon as possible.

Thanks again

seratch commented 1 year ago

@ChristopheFlimo Sorry, I am not a Google Cloud professional, so I cannot help you on these questions. I’ve never heard of such issues. I’d suggest asking questions in Google Cloud’s broader communities and stackoverflow.com.

Also, if you’re okay to switch to a different solution, Google Cloud Run should be much easier.

I believe we’ve answered your question related to bolt-js here. Would you mind closing this issue now?

ChristopheFlimo commented 1 year ago

Just one last question, do you have tutorial on bolt and Cloud run by any chance? Otherwise please close this issue.

seratch commented 1 year ago

We have the one for AWS Lambda but don’t for Google Cloud. The issues I’ve linked above are the only resources we provide at this moment.

Thanks a lot for your understanding! Let me close this.