< Home March 2019 Auto Deploying Lambda

Introduction

"Auto-deploy" is where code that has been pushed to your CI system is automatically deployed to the production servers without the need for human intervention.

Why is auto-deploy good?

Pre-deploy tests help avoid bad deploys

The gitlab web interface showing a failing test with the commit message 'Add Failing Test' followed by a successful test with the commit message 'Fix Bug'

You've (obviously) spent considerable time writing a bunch of comprehensive unit tests for your project, but all that is for nothing if you forget to check them before deploying the code to production. By having an automated deploy system the checks can also be run automatically before every deploy, helping to avoid bad code slip past any caffeine-deprived code reviewer.

Easy revert of a bad deploy

The gitlab web interface showing a failing test with the commit message 'Add Failing Test' followed by a successful test with the commit message 'Fix Bug'

If the tests are however not as comprehensive and planned and bad code does sneak into production, you can revert to a previous deploy by simply re-running the previous CI run on the last working commit. Giving you time to get a more permanent fix in place.

Git is an accurate indication of whats on prod

When manually managing servers it's easy to get confused. Which version is deployed currently? Do all servers have the same version? The same package versions? By having deploys managed automatically you can be sure whatever is in git is exactly what is in production.

Can use gitlab/githubs permissions to control who can deploy

The gitlab web interface showing the setup of a protected branch. The branch 'master' is selected and the UI indicates that 1 role is allowed to merge.

It's obviously advisable to ensure that the new intern can't get their bug riddled hello world app deployed without oversight. Ensuring that doesn't happen is easy however, just mark master as a protected branch to ensure only specific people are able to do the final step and release the code into the wild. You can also restrict PRs to require a second reviewer so every code gets multiple checks before deploy.

Deployer doesn't need key (so more secure)

By having the CI system, do the deploy it means the developers who do the code reviews don't need to give them the API keys for production, significantly reducing the security risk of ensuing everyone with deploy permissions keeps their keys safe.

Doing it yourself

Lets have a go at doing this. My project is a couple a function that runs in AWS lambda to return visitor analytics for this blog. The code is stored on GitLab so lets look at using GitLab workers to get this working.

Deploying lambda from a terminal

First we need to write the deploy script that will take the code and "deploy" it. What a deploy actually involves will depend on your system, it might be uploading the code to the server, generating a docker image and sending it to kubernetes or in my case zipping the code up and uploading it to aws.

Here is my script that deploys a lambda function by installing the node packages needed with npm, then ziping everything up and uploading them to AWS with their command line tool.

# Build the code
cd ./api
npm install
zip -r ../api.zip .
cd ..

# Upload to AWS
aws lambda update-function-code --function-name analytics-api --zip-file fileb://api.zip --publish

# Remove build assets
rm api.zip

Once that's working it's time to tell GitLab to run it when a new commit is pushed to master.

Using GitLab workers to auto deploy

Setup a .gitlab-ci file

GitLab workers are configured by committing a .gitlab-ci.yml file to the repository. That file defines how to test, build and deploy your code. Below is my setup that first runs the test script for all branches and if it's the master branch and the tests passed, it runs the deploy.sh script above to release the code to the world. For more information on this check out the GitLab docs.

stages:
  - test
  - deploy

run_tests:
  image: node:6.11.2
  stage: test
  script
  - make test

deploy_prod:
  image: python:latest
  stage: deploy 
  only:
  - master
  script:
  - apt-get update -qq && apt-get install -y -qq nodejs zip
  - pip install awscli
  - bash deploy.sh

Setup the API keys

After doing the above you will probably get an error, we didn't give GitLab permission to do the deploy!

The gitlab web interface showing the creation of 3 CI environment variables, AWS ACCESS KEY ID, AWS DEFAULT REGION, AWS SECRET ACCESS KEY

You don't want to include these API keys in the code, so instead they should be given to the CI as environment variables. So login to AWS, create a new API user with the required permissions & add the keys into GitLab. The AWS command line tool will automatically detect and use these keys from the environment variables, so make a commit and see if it worked.

Conclusion: Easier than expected

The thought of automatic deployments might seem scary and difficult, but in reality it might be easier than you think and could be as simple as spending 5 minutes throwing together a small script.