Unable to deploy a service using local packages
mzmiric5 opened this issue · comments
This is a Bug Report
Description
When attempting to package or deploy a service which uses local packages either referenced via file:
or yarn-workspace definitions, the deploy/package step that triggers the webpack build throws an error with
Command failed: yarn install --frozen-lockfile --non-interactive
error An unexpected error occurred: "Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.".
Running yarn install --frozen-lockfile --non-interactive
manually works just fine, so that points to an issue with serverless-webpack
.
For bug reports:
- What went wrong?
sls deploy
andsls package
fail with"Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`."
error when using a local package - What did you expect should have happened?
The service should have been packaged and deployed successfully - What was the config you used?
- What stacktrace or error message from your provider did you see?
@HyperBrain as requested in #369 I've opened a separate issue. I also went ahead and prepared a minimal repro repo with the config and dependencies set up that cause these issues to surface. https://github.com/mzmiric5/sls-wp-build-error-repro
Some notes:
- services/sls-only is a template without webpack, which deploys correctly and has no problems running on AWS
- shared/third-party-private is a placeholder for a package we are unable to share, but the fact that the package we are using has this one specific dependency is causing npm repro to fail with an error on npm install inside the sls package/deploy step
- our team primarily uses yarn, so this is our primary concern, and services/sls-wp-yarn shows the issue the best, as it fails with both the third-party-private package and the moment-wrapper example package (which the npm packager doesn't have an issue with)
For feature proposals:
- What is the use case that should be solved. The more detail you describe this in the easier it is to understand for us.
- If there is additional config how would it look
Similar or dependent issue(s):
Additional Data
- Serverless-Webpack Version you're using: 5.1.1
- Webpack version you're using: 4.5.0
- Serverless Framework Version you're using: 1.26.1
- Operating System: macOS Sierra 10.12.6
- Stack Trace (if available):
I ran into this exact same problem today. My yarn.lock file is up-to-date but the build still reports that it isn't. The command that fails in the build process runs without issue when executed manually.
Hi @nickelstar ,
Can you check the package.json
files that are generated by the plugin during deployment? You should find them after the error happens in the .webpack/dependencies
and .webpack/service
or .webpack/---function-name--
folders. It might be that a dependency you have is wrongly put into devDependencies
and as a consequence is not installed and packaged during the deployment.
The frozen-lockfile
error should reliably detect such errors, even if it does not show the exact reason without deeper inspection.
Thanks for the helpful info. When I looked at .webpack/dependencies/package.json, I noticed a package listed with an empty version number:
"dependencies": {
"aws-sdk": "",
This struck me as odd since I don't use aws-sdk and it's not listed in my package.json. So I added it to my package.json via 'yarn add aws-sdk'. After that, the error went away and deployments started working with yarn specified as the webpack packager.
@nickelstar Good to hear that. I think you can even move the aws-sdk to devDependencies
as it will be found but eventually omitted when packaging, because AWS already provides it in theiy Lambda environment. That will reduce your package sizes again.
@HyperBrain
I have this dependencies:
"dependencies": {
"moment": "^2.20.1",
"moment-timezone": "^0.5.14",
"mongodb": "^2.2.33",
"mssql": "^4.1.0",
"object.values": "^1.0.4",
"papaparse": "^4.3.6",
"slug": "^0.9.1",
"source-map-support": "^0.5.0",
"sprintf-js": "^1.1.1",
"underscore": "^1.8.3"
},
"devDependencies": {
"aws-sdk": "^2.172.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.3",
"babel-jest": "^22.1.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-flow": "^6.23.0",
"eslint": "^4.16.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-flowtype": "^2.40.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jest": "^21.7.0",
"flow-bin": "^0.63.1",
"flow-typed": "^2.4.0",
"glob": "^7.1.2",
"jest": "^22.2.0",
"serverless": "^1.25.0",
"serverless-log-forwarding": "^1.1.6",
"serverless-offline": "^3.16.0",
"serverless-secrets": "https://github.com/franciscocpg/serverless-secrets.git#e623994662366b6fcfe7cc40f1d85fd19b5029cd",
"serverless-webpack": "^5.1.1",
"webpack": "^3.10.0",
"webpack-node-externals": "^1.6.0",
"webpack-plugin-copy": "^1.0.1"
}
and then I see this .webpack/dependencies/package.json
generated:
{
(...)
"dependencies": {
"mongodb": "^2.2.33",
"mssql": "^4.1.0",
"object.values": "^1.0.4",
"source-map-support": "^0.5.0",
"moment": "^2.20.1",
"lodash": "",
"slug": "^0.9.1",
"moment-timezone": "^0.5.14",
"papaparse": "^4.3.6",
"underscore": "^1.8.3",
"sprintf-js": "^1.1.1"
}
}
This empty lodash ("lodash":""
) is causing the Your lockfile needs to be updated, but yarn was run with --frozen-lockfile
error for me.
If I remove it yarn install --frozen-lockfile --non-interactive
runs successfully. Do you have some idea what is causing this empty lodash?
Also when I run sls package
I got a lot of warnings like this: WARNING: Could not determine version of module lodash
.
@franciscocpg That is strange. The lodash in the package.json points out that webpack deteceted it as a primary dependency of your code, but it seems to be missing in your original package.json.
This can happen if you use it directly in your code (by using import or require lodash) but forgot to add it as dependency. If any of your dependencies brings lodash in, you won't recognize the error locally, because it is implicitly in the node_modules folder. NPM might swallow such issues, but yarn - with it's better optimization - will bring it to the surface.
So I'm sure that the root cause is, that you use lodash somewhere but did not add it as explicit dependency.
@HyperBrain
I've search for all occurrences of "lodash" in my entire project and I'm not using it anywhere.
I guess is some problem related to transitive dependencies and how yarn
is resolving it.
Anyway I was able to workaround it by adding "lodash": "^4.17.10"
to my dependencies
.
@franciscocpg Yes, you're right. This looks like a bug in the Yarn dependency tree transform (packager/yarn.js
) and it seems to fail to retrieve the version numbers of 2nd level dependencies.
Cannot be much. I'll have a look later this week.
However, the case that a version cannot be retrieved can still happen even if the bug is fixed. Would it be wise and safe to assume @latest
in these cases (additionally to the printed warning)?
Just struck this too (the original issue with local packages, not the lodash problem).
My local package is called shared
. In the project directory it's referred to in files as:
package.json
:"shared": "file:../shared/dist/",
yarn.lock
:"shared@file:../shared/dist":
But in .webpack/dependencies
it's referred to as:
package.json
:"shared": "file:../../../shared/dist/",
yarn.lock
:"shared@file:../shared/dist":
So the relative link in package.json
has been fixed up with the move, but not the lock file. So yarn correctly fails but that might be tricky to correct for...
@damonmaria Yes, that's exactly the problem. For npm
we implemented a lock file rebasing for file references, for yarn I did not, because I missed it.
In theory the same approach as with npm should work (that's an easy one). I'll prepare a PR soon and handle this with high prio so that you can try and test that later.
I'm working on a solution right now. However, there are 2 cases how local files can be integrated with yarn, so both need a proper handling:
case 1: yarn add my-module ../../somedir/mymodule
case 2: yarn add my-module file:../../somedir/mymodule
which lead to different representations in package.json as well as in yarn.lock
I'll do a first try to rebase any version reference that is file-like. If we encounter issues with that, we could - at least for now - restrict file references to use only the file:
notation to make the use case work.
@franciscocpg I think we should separate the 2 issues contained in this one into 2 issues.
I will fix the "local file references not handled" here and close it with the PR, but I think thet the dependency issue with yarn and transient dependencies is important too and should be solved and discussed properly.
@HyperBrain
That makes sense.
I'm going to be out on the next 2 weeks so I'm unable to help during this period.
About the yarn and transient dependencies
currently we can use this #370 (comment) as a workaround so I think is not too critical.
@franciscocpg Agree & no problem 😄 . Just tested the attached PR #376 and for me it worked now locally with yarn + file references. I'll add some unit tests, but anyone here (@damonmaria , @mzmiric5 ) can already test if it solves the problem.
I actually worked around this. My use case was sharing a project package across the different parts of the project. Once I struck this (and similar issues with the same shared package in non-Serverless parts of the project ) I instead installed the package (again as a file:
URL) in the root of the project. It no longer needs to be moved as each part of the project is built, and when node and Webpack search for it they look up the tree, out of the sub-project into the root of the project. Webpack seems to handle this fine, pulling in the code at build time.
@HyperBrain just tested the PR branch with our private package and this fixed the issue we were having. Thanks a lot for a quick fix.
Released with 5.1.3
I'm experiencing this issue using serverless-webpack 5.2.0. I have private scoped packages, and one of the dependencies that are defined in my private package is showing up without a version in .webpack/dependencies/package.json
. However, it appears to be correct in the yarn.lock
in that directory. I am whitelisting my scoped packages in the webpack config.
externals: [nodeExternals({
whitelist: [/^@my-scope/],
})],
I am using serverless-webpack
version 5.2.0
and also experiencing this error. Running the command yarn install --frozen-lockfile --non-interactive
returns with no error and reports that it was already up-to-date. What should I be trying?
I found that somehow that my dependency on axios
which had been there had been removed. Not surprising it failed then but the error really misleading.
I'd appreciate some advice on this issue to see if it's been resolved. I've been trying to deploy a serverless application that uses a local private package managed by Yarn Workspaces with no success, despite repeated different attempts I still get stuck with:
Error --------------------------------------------------
yarn install --frozen-lockfile --non-interactive failed with code 1
error An unexpected error occurred: "https://registry.yarnpkg.com/@private-package/foo: Not found".
(Even though things build outside of building with serverless-webpack
).
I'm now about to try a different approach and publish the private package to a private npm repository, but before I start that I'm researching whether this is likely to suceed.
We are using Yarn as our package manager, so would definitely prefer to continue, but I would love to know if that is likely to succeed, and if switching to npm would make it more likely?
Thanks in advance.
@danrivett, I was able to get serverless-webpack working in yarn monorepos by whitelisting them like so in the webpack config file..
externals: [
nodeExternals({
whitelist: ['private_package_1', 'private_package_2']
})],
@danrivett, I was able to get serverless-webpack working in yarn monorepos by whitelisting them like so in the webpack config file..
externals: [ nodeExternals({ whitelist: ['private_package_1', 'private_package_2'] })],
This worked perfectly for me, except the parameter name is different:
externals: [nodeExternals({ **allowlist**: ['private_package_1', 'private_package_2'], })],
Thank you for showing me the way...