This adventure started when I decided to develop a lambda in Go with SAM just to go through the development process and workflow, especially compared to the experience with Python.
I don’t know if you are like me, but I really dislike hitting the up arrow in my IDE terminal over and over when coding to rebuild a project or to launch something repeatedly.
Here is my experience navigating through this annoyance to avoid this rebuild/refresh cycle and the solution that I implemented.
Initiating the Project
I ended up initiating my SAM project with no options to just to see what options were available:
| |
After a few choices, I ended up with the following project configuration/options:Details
-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: go (provided.al2023)
Architectures: x86_64
Dependency Manager: mod
Application Template: hello-world
Output Directory: .
Configuration file: sam-app/samconfig.toml
Next steps can be found in the README file at sam-app/README.md
Updating the Architecture
I wanted to change the architecture to arm64 so I replaced x86_64 with arm64 in the template.yaml file.
| |
Local Development
All right, I am ready to get going on developing, so to speak..
| |
After SAM starts the API, I needed to rebuild my binary before invoking my lambda locally or I have to restart the SAM API server.
Details
Here is the rebuild workflow after making any code changes..
CTRL + C
sam build
sam local start-api
Solution with Nodemon
I abandoned working on the lambda at this point and wanted to improve my developer experience while working on the lambda.
This is where nodemon watching for changes in the workspace comes in.
{{ highlight bash “linenos=table” >}} npm install -g nodemon {{ }}
With nodeman, any changes where the application is watching will execute a command with the following:
| |
Adding a Bash Script
I made a basic shell script that nodemon will launch on file changes that kills the process for SAM API, rebuilds the binary file, and restart the SAM API server.
I added an option for builds as well, incase I even want to run sam local invoke HelloWorldFunction
#!/usr/bin/env bash
if [[ "$1" == "api" ]]; then
echo -e "Restarting API..."
# Kill any existing sam local start-api processes
pkill -f "sam local start-api"
# Wait for all sam local start-api processes to terminate
while pgrep -f "sam local start-api" > /dev/null; do
echo "Waiting for sam local start-api to fully stop..."
sleep 0.5
done
echo "sam local start-api stopped."
# Build project that is in the hello-world directory
GOARCH=arm64 GOOS=linux go -C hello-world build -o bootstrap
# Start the local API
sam local start-api
elif [[ "$1" == "build" ]]; then
echo -e "Building bootstrap.."
# create new build
make build
else
echo "Usage: $0 {api|build}"
exit 1
fi
Putting it all together
| |
At this point, I was really happy with the progress and solution.
The only other thing I wanted to add was adding commands in the projects Makefile for not having to find this command in the history when working on this project.
Here is my Makefile after adding deploy, delete, and nodemon options
| |
I am now able to run make watch-api and my lambda local dev environment experience has improved greatly with auto refreshing builds.
Template on GitHub
I have also added the example here into a template repository that anyone can clone or deploy to your own repo if you are interested - https://github.com/mjgard/go-lambda-arm64-template