AWS Developer Tools Blog
Automatically deploy a Serverless REST API from GitHub with AWS Chalice
AWS Chalice lets you quickly create serverless applications in Python. When you first start using Chalice, you can use the chalice deploy
command to deploy your application to AWS without any additional setup or configuration needed other than AWS credentials. As your application grows and you add additional team members to your project, you’ll want a system that can automatically deploy your application instead of remembering to run chalice deploy
every time you make a change to your app. One way to do this is use AWS CodeBuild and AWS CodePipeline to build and deploy your application whenever changes are pushed to a Git repository.
You can set this process up by using the AWS Console or by creating an AWS CloudFormation template for your deployment pipeline, but Chalice includes functionality to automatically generate a deployment pipeline template for you. In this post, we’ll show you how to set this up.
Walkthrough
To demonstrate this, we’ll create a Chalice application and configure it to automatically deploy whenever we push our changes to GitHub. To follow along you’ll need:
- Python 3.7 or higher
- The AWS CLI installed and configured
- A GitHub account
First we’ll need to create a new development environment and create a new Chalice application.
$ python3 -m venv /tmp/venv37
$ . /tmp/venv37/bin/activate
$ pip install chalice
$ chalice new-project testpipeline
$ cd testpipeline
Next, we’ll configure a local Git repository for our app.
$ git init .
$ git add -A .
$ git commit -m "Initial commit"
[master (root-commit) c35d315] Initial commit
4 files changed, 40 insertions(+)
create mode 100644 .chalice/config.json
create mode 100644 .gitignore
create mode 100644 app.py
create mode 100644 requirements.txt
Now that we’ve done that, we’ll need to create a GitHub repository for our application. You can go to the Create a New Repository page on GitHub and follow the steps to create a new repository. This can be either a public or private repository. Once you’ve created your repository, you’ll need to add GitHub as a remote for your application.
$ git remote add origin git@github.com:YOUR-NAME/YOUR-PROJECT.git
$ git push origin master
Now that we’ve configured GitHub we can configure our deployment pipeline. Instead of writing this pipeline definition by hand, Chalice includes a generate-pipeline
command that can generate a starter template for you. We’ll use this command to create our initial template.
$ mkdir infrastructure
$ chalice generate-pipeline \
--source github \
--buildspec-file buildspec.yml \
--pipeline-version v2 \
infrastructure/pipeline.json
In the command above there’s several arguments we’re providing. The --source github
argument is used to configure our pipeline to deploy from a GitHub repository instead of an AWS CodeCommit repository. The --buildspec-file
argument is used to specify that we want a buildspec file generated instead of being included inline with our CloudFormation template, and the --pipeline-version
specifies that we want to generate a v2 template instead of the default v1 template. The v2 template includes several improvements over the v1 template including using the latest CodeBuild images and the latest Buildspec specification. See the Chalice documentation for more details.
This command will generate two files, a buildspec.yml
file and an infrastructure/pipeline.json
file. We’ll add these files to our Git repository.
$ git add buildspec.yml infrastructure/pipeline.json
$ git commit -m "Add deployment pipeline template"
We’re almost ready to deploy our pipeline. In order for AWS CodePipeline to retrieve changes from our GitHub repository, we must provide an access token that our pipeline can use. To do this, we’ll create a personal access token on GitHub and store this value in AWS Secrets Manager. Our CloudFormation template will then reference this secret so that we don’t hardcode our access token in our template. You can follow the GitHub documentation on how to generate a personal access token. The AWS Secrets Manager documentation has a tutorial on how to store and retrieve secrets. You can also use the AWS CLI to create a new secret. Create a file named /tmp/secrets.json
with the following contents:
{"OAuthToken": "abcdefghhijklmnop"}
Be sure to replace the value with your own personal access token. Next run this command to create a new secret.
$ aws secretsmanager create-secret --name GithubRepoAccess \
--description "Token for Github Repo Access" \
--secret-string file:///tmp/secrets.json
We can now deploy our pipeline. We’ll use the AWS CLI to deploy our CloudFormation template.
$ aws cloudformation deploy --template-file infrastructure/pipeline.json \
--stack-name MyChaliceApp --parameter-overrides \
GithubOwner=repo-owner-name \
GithubRepoName=repo-name \
--capabilities CAPABILITY_IAM
Be sure to replace the GithubOwner
and GithubRepoName
with your own values.
Once our stack is created, we can go to our the CodePipeline page in the AWS Console and we’ll see that our pipeline was created.
Our application will take a few minutes to deploy. Once the last stage in our pipeline was finished running we can now test our application.
To test our application, we’ll need to retrieve the EndpointURL
associated with our application. You can go to the CloudFormation console page and lookup the value of EndpointURL
in the stack outputs tabs.
Now we can make a GET request to our endpoint URL we’ll see our hello world response:
$ curl -w '\n' https://rest-api-id.execute-api.us-west-2.amazonaws.com/api/
{"hello":"world"}
At this point, we have our deployment pipeline set up. Any changes to our GitHub repository will automatically be deployed. To test this, make a change to your app.py
file.
from chalice import Chalice
app = Chalice(app_name='testpipeline')
@app.route('/')
def index():
return {'hello': 'world, these are new changes!'}
We’ll now commit and push our changes.
$ git add app.py
$ git commit -m "Change hello world message"
[master 68cfc91] Change hello world message
1 file changed, 1 insertion(+), 3 deletions(-)
$ git push origin master
After a few minutes, we can see that application has been deployed.
$ curl -w '\n' https://rest-api-id.execute-api.us-west-2.amazonaws.com/api/
{"hello":"world, these are new changes!"}
Next Steps
Now that we have our deployment pipeline in place, there’s a few things we can do from here.
- Continue building out our application by modifying our
app.py
file. - Change the
buildspec.yml
file to modify how our application is built. We can add additional commands to run unit tests, run linters, type checkers, etc before we deploy our application. - Modify our
infrastructure/pipeline.json
file to add new stages to our deployment pipeline. You’ll need to rerun theaws cloudformation deploy
command if you make changes to your deployment pipeline.
If you’d like to deep dive on deploying your application with Chalice, our documentation goes into more detail and has additional options for you to consider. Let us know what you think! You can give feedback on our GitHub page.