Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sam local start-api doesn't update on changes #1921

Closed
kamrankhanwastaken opened this issue Apr 14, 2020 · 23 comments
Closed

sam local start-api doesn't update on changes #1921

kamrankhanwastaken opened this issue Apr 14, 2020 · 23 comments
Labels
blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale.

Comments

@kamrankhanwastaken
Copy link

kamrankhanwastaken commented Apr 14, 2020

Description

I am using the sample hello-world application on nodejs12.x using sam init but when I invoke sam build and sam local start-api any subsequent changes I make to the lambda function don't update on the port.

Steps to reproduce

sam init
Choice: 1 (AWS Quick Start Templates)
Runtime: 1 (nodejs12.x)
cd sam-app
sam build && sam local start-api

Inside the hello-world/app.js response object I change the message property and save.

Observed result

I refresh 127.0.0.1:3000/hello on the browser and nothing changes.

Expected result

I should see the message updated as per how sam local start-api is meant to work.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

sam --version
SAM CLI, version 0.47.0

docker --version
Docker version 19.03.8, build afacb8b

aws --version
aws-cli/1.11.80 Python/2.7.10 Darwin/18.7.0 botocore/1.5.43

@kamrankhanwastaken kamrankhanwastaken changed the title sam local start-app doesn't update on changes sam local start-api doesn't update on changes Apr 14, 2020
@jfuss
Copy link
Contributor

jfuss commented Apr 14, 2020

@fakekamrankhan Did you rebuild after changes? You need to run sam build again for code changes to be reflected.

@jfuss jfuss added the blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale. label Apr 14, 2020
@kamrankhanwastaken
Copy link
Author

kamrankhanwastaken commented Apr 14, 2020

Hmmm, I was under the impression that I could work on an existing function without needing to rebuild:

You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template

@kamrankhanwastaken
Copy link
Author

Apologies, I have dug a little further on this github repository and realize this isn't possible for now. Kind of a bummer because it is quite annoying as a development experience to have to constantly build after every change.

I believe this is the correct issue for tracking: #921

For now, anyone coming up here for the same confusion, this is what I'm doing to improve my experience in the interim:

npm i -g nodemon
nodemon --exec sam build

I run this in the root folder of my sam application in one terminal and run sam local start-api in another. This builds on every save so I don't have to do it manually.

Closing this issue.

@rpstreef
Copy link

rpstreef commented May 7, 2020

When looking at this issue, what is reported in the CLI tool You only need to restart SAM CLI if you update your AWS SAM template and what it actually does, does not correspond.

Is there an intention to fix this bug? Or was this never intended to work like this in the first place?

@jfuss
Copy link
Contributor

jfuss commented May 7, 2020

@rpstreef This isn't a bug. The log statement predates build so maybe there is an update to the message but everything is working as intended. sam build will produce a template that has the updated built artifacts. sam local start-api reads that template to stand up the endpoint. You still do not need to restart sam local start-api if your code changes but you do need to update the artifacts build produced by running sam build again. Otherwise, the code changes you made are not represented in the built artifacts within .aws-sam/build and will not update in the next invoke of the function.

@rpstreef
Copy link

rpstreef commented May 7, 2020

okay but it's clear this message is causing a lot of confusion. It's updating something else automatically but not the code. That isn't immediately obvious.

@jfuss
Copy link
Contributor

jfuss commented May 7, 2020

@rpstreef What's your recommendation? Are you interested in submitting a PR with an updated message?

@rpstreef
Copy link

@rpstreef What's your recommendation? Are you interested in submitting a PR with an updated message?

You need to either update your documentation that actually suggests hot reloading of code does work or you need to implement it:

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-start-api.html

That GIF image clearly demonstrates the hot reloading of code changes.

My recommendation is to implement that, or otherwise to just remove the message in the CLI all together.

@jfuss
Copy link
Contributor

jfuss commented May 14, 2020

I will see if there is a better way to communicate that.

We still allow 'hot reloading'. In the gif, there is no build stage happening. The key here is that the 'hot reloading' happens on whatever template is being used by the command. In build cases, this is the generate build template. This is why you can build, start the api, change code, build and invoke without having to tear down the start-api command. In the non build case, it happens just like the gif.

Sounds like the confusion stems from using this with build not that we don't support it (because we do).

@rajmayank
Copy link

This is confusing indeed, but there is a workaround. If the ./aws-sam/build/ is empty, the source version of the functions are used instead of the built. Note that the first is dynamic and the later is not.

So, instead of bundling my dependencies in the main function, I took a much cleaner approach - bundle my dependencies within a lambda layer. Which should be the first choice in any case.

While running the local api, I simply delete the ./aws-sam/build/ directory and start the api.
Here is how my package.json looks like:

  "scripts": {
    ....
    "local:dep:python:lambda":  "rm -rf ./lambdas/layers/venv/python/ && pip install -r requirements.txt -t ./lambdas/layers/venv/python/",
    "sam:start-api": "sam local start-api",
    "local:api": "rm -rf .aws-sam/build/ && npm run local:dep:python:lambda && npm run sam:start-api"
  }

Also the sam template references the layer that corresponds to the package dependencies:

      ....
      Layers:
        - !Ref FunctionAssetsLayer
        - !Ref **FunctionDependenciesLayer**

On a side note, @jfuss I'm new to sam but would like to take this up. I haven't used it enough to get hang of the access patterns, so can you help me with what would be the ideal way to fix this ?

@alyyousuf7
Copy link

languages like Node & Python, or a build directory that stores your compiled artifacts or a JAR file. If you are using
a interpreted language, local changes will be available immediately in Docker container on every invoke. For more
compiled languages or projects requiring complex packing support, we recommended you run your own building solution
and point SAM to the directory or file containing build artifacts.

I believe the solution to this would be to not use .aws-sam/build for interpreted languages?

@mikebell
Copy link

oh wow this is really confusing. What's the correct development workflow for the following situation:

I'm building a python lambda function, I start playing around with just the default lambda function adding in code and seeing my changes in real time. I then add another python package in which case I need to run sam build for the requirements.txt to be picked up. I then start adding more code to my function but I don't see any of the changes until I run sam build again.

Should I be using a task runner to sam build every time the function changes? How do you pull in external packages without breaking the really really useful functionality of sam local start-api?

@rtrive
Copy link

rtrive commented Nov 28, 2020

how could i work with libraries in requirements.txt ? Because if i don't use sam build i could not work in this case

@jjercx
Copy link

jjercx commented Dec 28, 2020

I can confirm it hot reloads if you don't have the build folder there.

@jfuss
Copy link
Contributor

jfuss commented Dec 29, 2020

If you are using sam build, you MUST sam build after a code change to have the new files loaded for sam local start-api. sam local start-api loads the CodeUri Property into the container. When using build, this is the .aws-sam/build folder. So in order for new changes to be reflected, you need to rebuild to put the files into that location, otherwise its the same files as the first time you built.

@rpstreef
Copy link

rpstreef commented Jan 7, 2021

@jfuss there's still a lot of explanation required for this feature, in my opinion this is simply due to unclear documentation.

Fix the documentation, and the problem goes away.

@6Hhcy
Copy link

6Hhcy commented Feb 22, 2021

This is confusing indeed, but there is a workaround. If the ./aws-sam/build/ is empty, the source version of the functions are used instead of the built. Note that the first is dynamic and the later is not.

So, instead of bundling my dependencies in the main function, I took a much cleaner approach - bundle my dependencies within a lambda layer. Which should be the first choice in any case.

While running the local api, I simply delete the ./aws-sam/build/ directory and start the api.
Here is how my package.json looks like:

  "scripts": {
    ....
    "local:dep:python:lambda":  "rm -rf ./lambdas/layers/venv/python/ && pip install -r requirements.txt -t ./lambdas/layers/venv/python/",
    "sam:start-api": "sam local start-api",
    "local:api": "rm -rf .aws-sam/build/ && npm run local:dep:python:lambda && npm run sam:start-api"
  }

Also the sam template references the layer that corresponds to the package dependencies:

      ....
      Layers:
        - !Ref FunctionAssetsLayer
        - !Ref **FunctionDependenciesLayer**

On a side note, @jfuss I'm new to sam but would like to take this up. I haven't used it enough to get hang of the access patterns, so can you help me with what would be the ideal way to fix this ?

Is there a workaround for Python?

@rajalokan
Copy link

Is there a workaround for Python?

Same here. Please share if anyone has sorted this.

I wonder how chalice does hot reload. I'm sure this should be implemented for python. Looking forward to a resolution. Thanks.

@Dlozitskiy
Copy link

approach with layers may work for python as well without platform specific wheels in the dependencies:

template.yaml:

  FunctionLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      CompatibleRuntimes: 
        - python3.8
      ContentUri: code/function-layer/.
    Metadata:
      BuildMethod: python3.8

  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: code/function/
      Handler: app.lambda_handler
      Runtime: python3.8
      Layers:
        - !Ref FunctionLayer

install dependencies:

# cd code/function-layer
# pip install -r requirements.txt -t ./python

update and invoke without running sam build:

sam local invoke Function

@achan-godaddy
Copy link

for development purposes wouldn't it be possible to have an option to keep a local docker volume mount that points to a shared folder such as dist/app.js . Then the local system can watch and build using whatever tools needed and the docker image would just need to watch that one file and restart itself if it's currently warm?

@chrishart0
Copy link

This is confusing indeed, but there is a workaround. If the ./aws-sam/build/ is empty, the source version of the functions are used instead of the built. Note that the first is dynamic and the later is not.

So, instead of bundling my dependencies in the main function, I took a much cleaner approach - bundle my dependencies within a lambda layer. Which should be the first choice in any case.

While running the local api, I simply delete the ./aws-sam/build/ directory and start the api. Here is how my package.json looks like:

  "scripts": {
    ....
    "local:dep:python:lambda":  "rm -rf ./lambdas/layers/venv/python/ && pip install -r requirements.txt -t ./lambdas/layers/venv/python/",
    "sam:start-api": "sam local start-api",
    "local:api": "rm -rf .aws-sam/build/ && npm run local:dep:python:lambda && npm run sam:start-api"
  }

Also the sam template references the layer that corresponds to the package dependencies:

      ....
      Layers:
        - !Ref FunctionAssetsLayer
        - !Ref **FunctionDependenciesLayer**

On a side note, @jfuss I'm new to sam but would like to take this up. I haven't used it enough to get hang of the access patterns, so can you help me with what would be the ideal way to fix this ?

I noticed that this does not seem to work when using SAM with an image but does work when using a ZIP.

@nickstares
Copy link

for development purposes wouldn't it be possible to have an option to keep a local docker volume mount that points to a shared folder such as dist/app.js . Then the local system can watch and build using whatever tools needed and the docker image would just need to watch that one file and restart itself if it's currently warm?

Would love something like this

@jtlz2
Copy link

jtlz2 commented Sep 29, 2022

./aws-sam/build/ -> ./.aws-sam/build/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale.
Projects
None yet
Development

No branches or pull requests