Cannot deploy a new proejct
nathan-kinship opened this issue · comments
My problem seems related to this issue but is not directly addressed by any of the suggestions within it: twilio/twilio-cli#215
Versions are current: twilio-cli/5.3.3 darwin-arm64 node-v16.16.0
Following the documentation, I create a brand new project, correct the problems in its package.json which prevent it from compiling at all, and attempt to deploy it:
twilio serverless:init my-project --typescript
cd my-project
npm run build
twilio serverless:deploy (:)
Deploying functions & assets to the Twilio Runtime
Username SKf22618a36dfa62a811980e8a7d3f5871
Password AkpA****************************
Service Name my-project
Environment dev
Root Directory /Users/nate/dev/my-project
Dependencies @twilio-labs/serverless-runtime-types, twilio, @twilio/runtime-handler
Env Variables
Runtime node16
✖ Failed Deployment
│ ERROR Failed API Request 20001
│
│ At least one Function Version or Asset Version is required for Build
│
│ More info: https://www.twilio.com/docs/errors/20001
Why does the deploy tool not perform the actions which are required to deploy anything?
What exactly do I have to do for the deploy tool in order to make it capable of deploying something?
Why does the documentation tell me that the deploy tool should be capable of deploying when it clearly is not?
Hey @nathan-kinship apologies for that inconsistency. The problem is that in the TypeScript project we modify the npm scripts to pass --functions-folder
and --assets-folder
but this doesn't translate to the twilio serverless:deploy
command. The easiest solution here will be to modify the .twilioserverlessrc
file to include the following configuration:
{
"functionsFolder": "dist/functions",
"assetsFolder": "dist/assets"
}
This option didn't exist when the TypeScript template was created and we didn't adjust this logic when it was introduced.
Once you do those config changes you should be able to run:
npm run build
twilio serverless:deploy
And it should deploy correctly. I'll make sure we do the necessary changes to set this configuration during project setup and also update docs accordingly.
Thanks, but there was absolutely no change in the behavior at all. Did you actually try this yourself?
My .twilioserverlessrc
:
{
"commands": {},
"environments": {},
"projects": {},
// "assets": true /* Upload assets. Can be turned off with --no-assets */,
"assetsFolder": "dist/assets" /* Specific folder name to be used for static assets */,
// "buildSid": null /* An existing Build SID to deploy to the new environment */,
// "createEnvironment": false /* Creates environment if it couldn't find it. */,
// "cwd": null /* Sets the directory of your existing Serverless project. Defaults to current directory */,
// "detailedLogs": false /* Toggles detailed request logging by showing request body and query params */,
// "edge": null /* Twilio API Region */,
// "env": null /* Path to .env file for environment variables that should be installed */,
// "environment": "dev" /* The environment name (domain suffix) you want to use for your deployment. Alternatively you can specify an environment SID starting with ZE. */,
// "extendedOutput": false /* Show an extended set of properties on the output */,
// "force": false /* Will run deployment in force mode. Can be dangerous. */,
// "forkProcess": true /* Disable forking function processes to emulate production environment */,
// "functionSid": null /* Specific Function SID to retrieve logs for */,
// "functions": true /* Upload functions. Can be turned off with --no-functions */,
"functionsFolder": "dist/functions" /* Specific folder name to be used for static functions */,
// "inspect": null /* Enables Node.js debugging protocol */,
// "inspectBrk": null /* Enables Node.js debugging protocol, stops execution until debugger is attached */,
// "legacyMode": false /* Enables legacy mode, it will prefix your asset paths with /assets */,
// "live": true /* Always serve from the current functions (no caching) */,
// "loadLocalEnv": false /* Includes the local environment variables */,
// "loadSystemEnv": false /* Uses system environment variables as fallback for variables specified in your .env file. Needs to be used with --env explicitly specified. */,
// "logCacheSize": null /* Tailing the log endpoint will cache previously seen entries to avoid duplicates. The cache is topped at a maximum of 1000 by default. This option can change that. */,
// "logLevel": "info" /* Level of logging messages. */,
// "logs": true /* Toggles request logging */,
// "ngrok": null /* Uses ngrok to create a public url. Pass a string to set the subdomain (requires a paid-for ngrok account). */,
// "outputFormat": "" /* Output the results in a different format */,
// "overrideExistingProject": false /* Deploys Serverless project to existing service if a naming conflict has been found. */,
// "port": "3000" /* Override default port of 3000 */,
// "production": false /* Promote build to the production environment (no domain suffix). Overrides environment flag */,
// "properties": null /* Specify the output properties you want to see. Works best on single types */,
// "region": null /* Twilio API Region */,
"runtime": "node16" /* The version of Node.js to deploy the build to. (node16) */
// "serviceName": null /* Overrides the name of the Serverless project. Default: the name field in your package.json */,
// "serviceSid": null /* SID of the Twilio Serverless Service to deploy to */,
// "sourceEnvironment": null /* SID or suffix of an existing environment you want to deploy from. */,
// "tail": false /* Continuously stream the logs */,
// "template": null /* undefined */,
}
% twilio serverless:deploy --override-existing-project -l debug
[DEBUG] Config File: /Users/nate/.twilio-cli/config.json
[DEBUG] Using profile: dev
twilio-run:config:configLoader Load config +0ms
twilio-run:config:configLoader Config found at /Users/nate/dev/my-project/.twilioserverlessrc +7ms
twilio-run:config:credentials Using account credentials from Twilio CLI +0ms
twilio-run:config:configLoader Load config +2ms
twilio-run:config:configLoader Config cached in memory +0ms
twilio-run:internal:utils Attempting to read serviceSid from a deployinfo file +0ms
twilio-run:internal:utils Could not determine existing serviceSid +0ms
twilio-run:internal:utils AC9080a3ff3df9007f9c8bbb21ebdf6c96:us1 +0ms
twilio-run:deploy Deploy Config {
twilio-run:deploy cwd: '/Users/nate/dev/my-project',
twilio-run:deploy envPath: '/Users/nate/dev/my-project/.env',
twilio-run:deploy username: '[REDACTED]',
twilio-run:deploy password: '[REDACTED]',
twilio-run:deploy env: {},
twilio-run:deploy pkgJson: {
twilio-run:deploy name: '[REDACTED]',
twilio-run:deploy version: '[REDACTED]',
twilio-run:deploy private: '[REDACTED]',
twilio-run:deploy scripts: '[REDACTED]',
twilio-run:deploy dependencies: '[REDACTED]',
twilio-run:deploy devDependencies: '[REDACTED]',
twilio-run:deploy engines: '[REDACTED]'
twilio-run:deploy },
twilio-run:deploy overrideExistingService: true,
twilio-run:deploy force: false,
twilio-run:deploy serviceName: 'my-project',
twilio-run:deploy functionsEnv: 'dev',
twilio-run:deploy noAssets: false,
twilio-run:deploy noFunctions: false,
twilio-run:deploy runtime: 'node16',
twilio-run:deploy userAgentExtensions: [
twilio-run:deploy 'twilio-run/3.5.3',
twilio-run:deploy '@twilio-labs/plugin-serverless/3.1.3',
twilio-run:deploy 'twilio-run:deploy'
twilio-run:deploy ]
twilio-run:deploy } +0ms
Deploying functions & assets to the Twilio Runtime
Username SKf22618a36dfa62a811980e8a7d3f5871
Password AkpA****************************
Service Name my-project
Environment dev
Root Directory /Users/nate/dev/my-project
Dependencies @twilio-labs/serverless-runtime-types, twilio, @twilio/runtime-handler
Env Variables
Runtime node16
⠋ Deploying Function twilio-serverless-api:client Deploy config {
twilio-serverless-api:client cwd: '/Users/nate/dev/my-project',
twilio-serverless-api:client envPath: '/Users/nate/dev/my-project/.env',
twilio-serverless-api:client username: '[REDACTED]',
twilio-serverless-api:client password: '[REDACTED]',
twilio-serverless-api:client env: {},
twilio-serverless-api:client pkgJson: {
twilio-serverless-api:client name: '[REDACTED]',
twilio-serverless-api:client version: '[REDACTED]',
twilio-serverless-api:client private: '[REDACTED]',
twilio-serverless-api:client scripts: '[REDACTED]',
twilio-serverless-api:client dependencies: '[REDACTED]',
twilio-serverless-api:client devDependencies: '[REDACTED]',
twilio-serverless-api:client engines: '[REDACTED]'
twilio-serverless-api:client },
twilio-serverless-api:client overrideExistingService: true,
twilio-serverless-api:client force: false,
twilio-serverless-api:client serviceName: 'my-project',
twilio-serverless-api:client functionsEnv: 'dev',
twilio-serverless-api:client noAssets: false,
twilio-serverless-api:client noFunctions: false,
twilio-serverless-api:client runtime: 'node16',
twilio-serverless-api:client userAgentExtensions: [
twilio-serverless-api:client 'twilio-run/3.5.3',
twilio-serverless-api:client '@twilio-labs/plugin-serverless/3.1.3',
twilio-serverless-api:client 'twilio-run:deploy'
twilio-serverless-api:client ]
twilio-serverless-api:client } +0ms
twilio-serverless-api:fs Search for directory. Options: "functions,src" +0ms
twilio-serverless-api:fs Found Functions Directory "/Users/nate/dev/my-project/src" +0ms
twilio-serverless-api:fs Search for directory. Options: "assets,static" +0ms
twilio-serverless-api:fs Found Assets Directory "undefined" +0ms
⠴ Creating Service
twilio-serverless-api:services ClientApiError [TwilioApiError]: Service with this UniqueName already exists.
twilio-serverless-api:services at /Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/api/services.js:43:23
twilio-serverless-api:services at Generator.throw (<anonymous>)
twilio-serverless-api:services at rejected (/Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/api/services.js:7:65)
twilio-serverless-api:services at processTicksAndRejections (node:internal/process/task_queues:96:5) {
twilio-serverless-api:services code: 20409,
twilio-serverless-api:services url: 'https://serverless.twilio.com/v1/Services',
twilio-serverless-api:services details: {
twilio-serverless-api:services code: 20409,
twilio-serverless-api:services message: 'Service with this UniqueName already exists.',
twilio-serverless-api:services more_info: 'https://www.twilio.com/docs/errors/20409',
twilio-serverless-api:services status: 409
twilio-serverless-api:services }
⠧ Waiting for deployment.
twilio-serverless-api:builds ClientApiError [TwilioApiError]: At least one Function Version or Asset Version is required for Build
twilio-serverless-api:builds at /Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/api/builds.js:112:23
twilio-serverless-api:builds at Generator.throw (<anonymous>)
twilio-serverless-api:builds at rejected (/Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/api/builds.js:7:65)
twilio-serverless-api:builds at processTicksAndRejections (node:internal/process/task_queues:96:5) {
twilio-serverless-api:builds code: 20001,
twilio-serverless-api:builds url: 'https://serverless.twilio.com/v1/Services/ZS1dc8ce4c593591676842caadc25d5257/Builds',
twilio-serverless-api:builds details: {
twilio-serverless-api:builds code: 20001,
twilio-serverless-api:builds message: 'At least one Function Version or Asset Version is required for Build',
twilio-serverless-api:builds more_info: 'https://www.twilio.com/docs/errors/20001',
twilio-serverless-api:builds status: 400
twilio-serverless-api:builds }
twilio-serverless-api:builds } +0ms
twilio-run:deploy ClientApiError [TwilioApiError]: At least one Function Version or Asset Version is required for Build
twilio-run:deploy at convertApiErrorsAndThrow (/Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/utils/error.js:33:15)
twilio-run:deploy at TwilioServerlessApiClient.<anonymous> (/Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/client.js:515:54)
twilio-run:deploy at Generator.throw (<anonymous>)
twilio-run:deploy at rejected (/Users/nate/.twilio-cli/node_modules/@twilio-labs/serverless-api/dist/client.js:7:65)
twilio-run:deploy at processTicksAndRejections (node:internal/process/task_queues:96:5) {
twilio-run:deploy code: 20001,
twilio-run:deploy url: 'https://serverless.twilio.com/v1/Services/ZS1dc8ce4c593591676842caadc25d5257/Builds',
twilio-run:deploy details: {
twilio-run:deploy code: 20001,
twilio-run:deploy message: 'At least one Function Version or Asset Version is required for Build',
twilio-run:deploy more_info: 'https://www.twilio.com/docs/errors/20001',
twilio-run:deploy status: 400
twilio-run:deploy }
✖ Failed Deployment
│ ERROR Failed API Request 20001
│
│ At least one Function Version or Asset Version is required for Build
│
│ More info: https://www.twilio.com/docs/errors/20001
Hey @nathan-kinship apologies that you are still experiencing issues with the deployment and thanks from sharing the debug logs with me. From the debug logs it looks like the functionsFolder
and assetsFolder
configuration isn't found in /Users/nate/dev/my-project/.twilioserverlessrc
. I did try this myself and didn't run into any issues. I also created a couple of new projects and asked several colleagues to verify the following series of commands which worked for them.
twilio serverless:init ts-example --typescript && cd ts-example && npm install -D typescript@latest && echo '{ "functionsFolder": "dist/functions", "assetsFolder": "dist/assets" }' > .twilioserverlessrc && npm run build && twilio serverless:deploy
If the configuration gets correctly picked up you should also see in the debug logs functionsFolderName
and assetFolderName
accordingly.
Thanks; that sequence did indeed work.
Now how can I go about determining why the tool is ignoring my .twilioserverlessrc
? My actual goal here is not to deploy a brand new project, but to update an older project to use the newer build tools so the fact that it's not being picked up consistently seems like a big issue.
I was able to do this successfully with another project which was not using TypeScript and it worked without a hitch.
Seems like it's in the right location with the right permissions and the right content.
% cd my-project (:)
[~/dev/my-project] nate@kin % ls (:)
total 752
drwxr-xr-x 12 nate staff 384 Feb 7 09:39 .
drwxr-xr-x 20 nate staff 640 Feb 8 12:51 ..
-rw-r--r-- 1 nate staff 58 Feb 7 09:38 .env
-rw-r--r-- 1 nate staff 2086 Feb 7 09:38 .gitignore
-rw-r--r-- 1 nate staff 2 Feb 7 09:38 .nvmrc
-rw-r--r-- 1 nate staff 3481 Feb 7 09:38 .twilioserverlessrc
drwxr-xr-x 4 nate staff 128 Feb 7 09:39 dist
drwxr-xr-x 366 nate staff 11712 Feb 7 09:56 node_modules
-rw-r--r-- 1 nate staff 357006 Feb 7 09:56 package-lock.json
-rw-r--r-- 1 nate staff 805 Feb 7 09:56 package.json
drwxr-xr-x 4 nate staff 128 Feb 7 09:38 src
-rw-r--r-- 1 nate staff 218 Feb 7 09:38 tsconfig.json
Could you maybe point me to the spot in this repo where the file gets read in? Since I have the live test case it might be easier for me to debug now that we have established a root cause.
Interesting discovery... The way I was commenting and uncommenting individual lines in .twilioserverlessrc was making Prettier happy but they seemed to get parsed as though they weren't commented at all. I've just deleted every attribute I'm not actively using/testing and was able to deploy successfully with one lingering issue: the tool is not identifying the correct destination service and always wants to deploy to one called dialpad-functions
.
This is a real service in my account and it is one that I want to continue deploying to, but it's not the actual destination for this code. I've wiped out .twiliodeployinfo
and verified that the string dialpad-functions
appears nowhere inside this project, but the CLI continues to decide that's where everything belongs. What exactly is it pulling this information from and how can I make it stop?
✔ Serverless project successfully deployed
Deployment Details
Domain: dialpad-functions-3099-dev.twil.io
Service:
dialpad-functions (ZSb9f6bdb8158c4a4fdfa79ffd63861b1c)
Environment:
dev (ZEd1a76bed8a0b468081cc2a79992245dc)
Build SID:
ZB0b8a4a70281b47c3f03ecf50350dbd77
Without seeing your full project it's hard for me to tell where this is coming from but in general the logic is the following:
- Check if there is a specified
serviceSid
either passed in using--service-sid=
or through the.twilioserverlessrc
file (see Configuration docs on how to specify one either in general or per account SID). If thatserviceSid
can be found use that otherwise carry on - Check if there is a
.twiliodeployinfo
and look up if the Account SID you are using to deploy has a correspondingserviceSid
in it. If that's the case: use that one, otherwise carry on - Try to create a service with the name specified in the
.twilioserverlessrc
if specified - Try to create a service with the name in the
package.json
file
This is the full logic to determine it: https://github.com/twilio-labs/serverless-toolkit/blob/main/packages/twilio-run/src/config/deploy.ts#L92-L116
The debug logs should also include some pointers towards where it's coming. For example if it comes from the .twiliodeployinfo
it should say something like:
twilio-run:internal:utils Found service sid by region from deploy info, "ZS..."
Thanks; I think the remaining issues are on our side of the fence and do not belong in this discussion.
The takeaway for me is that an extremely generic exception handler is being relied upon to flag extremely specific problems in this tool and that is failing extremely predictably. Given the fact that the actual meaning of this mysterious error is "I don't like something about your build products" I believe this tool needs the following improvements:
- Ensure that new projects are configured in a working state as already discussed so that users can at least verify that the tool itself isn't fundamentally broken.
- Add integration testing to the release process to catch broken defaults before they go public.
- Add some new exception types and exit earlier with more relevant messages when an issue is discovered in a
functions
orassets
directory. If it's empty, say it's empty and return. If it doesn't exist, say it doesn't exist and return. If it contains something undesirable, like a.dart
file, say "Ignoring file XXXXXX.dart" and continue.
If these basic provisions were in place I more than likely could discovered the core issue myself, saving multiple weeks of my life exchanging frustrating emails with support reps who don't have any training with any of the tools they tell people to use beyond "copy and paste this over and over until they give up and go away."
I agree the error messages here were confusing and we'll make sure to address this. Sorry for the inconvenience.