181 lines
7.0 KiB
Markdown
181 lines
7.0 KiB
Markdown
---
|
|
title_tag: "Using Travis CI | CI/CD"
|
|
meta_desc: This page details how to use Travis CI to manage deploying
|
|
staging and production stacks based on commits to specific Git branches.
|
|
title: Travis CI
|
|
h1: Pulumi CI/CD & Travis CI
|
|
meta_image: /images/docs/meta-images/docs-meta.png
|
|
menu:
|
|
usingpulumi:
|
|
parent: cont_delivery
|
|
weight: 1
|
|
aliases:
|
|
- /docs/reference/cd-travis/
|
|
- /docs/console/continuous-delivery/travis/
|
|
- /docs/guides/continuous-delivery/travis/
|
|
- /docs/using-pulumi/continuous-delivery/cd-travis/
|
|
- /docs/guides/continuous-delivery/cd-travis/
|
|
---
|
|
|
|
This page details how to use [Travis CI](https://travis-ci.com/) to manage deploying
|
|
staging and production stacks based on commits to specific Git branches. This is sometimes
|
|
referred to as Push-to-Deploy.
|
|
|
|
Pulumi doesn't require any particular arrangement of stacks or workflow to work in a
|
|
continuous integration / continuous deployment system. So the steps described here can be
|
|
altered to fit into any existing type of deployment setup.
|
|
|
|
## Stack and Branch Mappings
|
|
|
|
The scripts below act on two hypothetical stacks: `acme/website-staging` and
|
|
`acme/website-production`. The source code for both stacks are in the same repository. And we will
|
|
update the `website-staging` stack whenever code is pushed into the `master` branch, and update the
|
|
`website-production` stack whenever code is pushed into the `production` branch.
|
|
|
|
We will also run previews of infrastructure changes for pull requests into the `master` and
|
|
`production` branches, to identify an potentially impactful changes before they get merged.
|
|
|
|
## Configuring Travis
|
|
|
|
To support this deployment strategy, you need to enable Travis to create both `push` and
|
|
`pull_request` jobs. In the Travis UI, this is done by checking the "Build pushed branches" and
|
|
"Build pushed pull requests" options.
|
|
|
|
`push` jobs are created when a Git push is made to a branch. We configure the build script for
|
|
`push` jobs to run `pulumi up`, i.e. carry out the push-to-deploy operation.
|
|
|
|
`pull_request` jobs are created when a push is made to a _pull request topic branch_. (That same
|
|
push will also trigger a separate `push` job.) We configure the `pull_request` job to run
|
|
`pulumi preview` to see any infrastructure changes that would happen as _a result of_ the pull
|
|
request being merged.
|
|
|
|
### Environment Variables
|
|
|
|
To use Pulumi within Travis CI, there are a few environment variables you'll need to set for each
|
|
build.
|
|
|
|
The first is `PULUMI_ACCESS_TOKEN`, which is required to authenticate with pulumi.com in order to
|
|
perform the preview or update. You can create a new
|
|
[Pulumi access token](/docs/pulumi-cloud/accounts#access-tokens) specifically for your
|
|
CI/CD job on your [Pulumi Account page](https://app.pulumi.com/account/tokens).
|
|
|
|
Next, you will also need to set environment variables specific to your cloud resource provider.
|
|
For example, if your stack is managing resources on AWS, `AWS_ACCESS_KEY_ID` and
|
|
`AWS_SECRET_ACCESS_KEY`.
|
|
|
|
## Scripts
|
|
|
|
With Travis configured, we then just need to add three files to the repository:
|
|
`.travis.yml`, `scripts/travis_push.sh`, and `scripts/travis_pull_request.sh`. (Though of course
|
|
you are free to rename and/or move these files to whatever makes sense in your repo.)
|
|
|
|
### Travis.yaml
|
|
|
|
The following is a minimal `.travis.yml`, which describes the steps Travis CI will perform as part
|
|
of building the repository.
|
|
|
|
If you already have an existing Travis configuration file, the only thing you'll need to add are
|
|
the steps to download the Pulumi CLI and add it to the path.
|
|
|
|
The example `.travis.yml` file then calls either `scripts/travis_pull.sh` or
|
|
`scripts/travis_pull_request.sh`, depending on the build type. However, if you already have a
|
|
build script or `Makefile` target to deploy your software, you can add the commands
|
|
to run Pulumi to that.
|
|
|
|
```yaml
|
|
language: generic
|
|
before_install:
|
|
- curl -fsSL https://get.pulumi.com/ | sh
|
|
- export PATH=$PATH:$HOME/.pulumi/bin
|
|
script:
|
|
- ./scripts/travis_${TRAVIS_EVENT_TYPE}.sh
|
|
```
|
|
|
|
### scripts/travis_push.sh
|
|
|
|
`scripts/travis_push.sh` is the script that is executed on `push` jobs. And for the push-to-deploy stategy,
|
|
is when we will run `pulumi up`. For `push` jobs, the `TRAVIS_BRANCH` environment variable is the
|
|
pushed branch. So we use that to determine which stack to update, e.g. pushes to `master` update the
|
|
staging stack and `production` update the production stack.
|
|
|
|
We can do this in Bash using a simple switch statement.
|
|
|
|
```bash
|
|
echo "Travis push job"
|
|
|
|
# Download dependencies and build
|
|
npm install
|
|
npm run build
|
|
|
|
# Update the stack
|
|
case ${TRAVIS_BRANCH} in
|
|
master)
|
|
pulumi stack select acme/website-staging
|
|
pulumi up --yes
|
|
;;
|
|
production)
|
|
pulumi stack select acme/website-production
|
|
pulumi up --yes
|
|
;;
|
|
*)
|
|
echo "No Pulumi stack associated with branch ${TRAVIS_BRANCH}."
|
|
;;
|
|
esac
|
|
```
|
|
|
|
### scripts/travis_pull_request.sh
|
|
|
|
`scripts/travis_pull_request.sh` is triggered on pushes to a pull request branch. For these jobs
|
|
the meaning of `TRAVIS_BRANCH` is the branch being _targeted_ by the pull request.
|
|
|
|
So if the pull request is going to be merged into the `master` branch, then we would want to
|
|
preview the changes that would be made to the staging stack. For pull requests targeting the
|
|
`production` branch, we want to preview the production stack.
|
|
|
|
```bash
|
|
echo "Travis pull_request job"
|
|
|
|
# Download dependencies and build
|
|
npm install
|
|
npm run build
|
|
|
|
# Preview changes that would be made if the PR were merged.
|
|
case ${TRAVIS_BRANCH} in
|
|
master)
|
|
pulumi stack select acme/website-staging
|
|
pulumi preview
|
|
;;
|
|
production)
|
|
pulumi stack select acme/website-production
|
|
pulumi preview
|
|
;;
|
|
*)
|
|
echo "No Pulumi stack targeted by pull request branch ${TRAVIS_BRANCH}."
|
|
;;
|
|
esac
|
|
```
|
|
|
|
## Concurrency
|
|
|
|
When using Travis to continuously deploy your Pulumi stacks, you may run into a problem. What
|
|
happens if there are multiple commits merged into the `master` branch in rapid succession?
|
|
|
|
Travis will trigger multiple `push` jobs, which will then both try to run `pulumi up` on the
|
|
same stack at the same time.
|
|
|
|
Pulumi blocks any stack updates while one is already in progress. (To avoid conflicting resource
|
|
updates or corrupting resource state.) So the stack and its resources won't be harmed by the
|
|
concurrent update, but it will likely fail your Travis build.
|
|
|
|
There are a few ways to address this, such as preventing Travis from starting concurrent builds.
|
|
However, the recommended way is to use the [travisqueue](https://github.com/pulumi/travisqueue)
|
|
tool.
|
|
|
|
`travisqueue` is a tool that you can add to your `.travis.yml` file to limit build concurrency on
|
|
a per-branch basis. This allows you to limit the number of concurrent builds for any branches that
|
|
are configured to perform a Pulumi update. So Travis will only have one build for the `master`
|
|
branch at a time, but could be running any number of concurrent builds for other branches.
|
|
|
|
See the [README.md](https://github.com/pulumi/travisqueue/blob/master/README.md) file for more
|
|
information on how it works and how to add it to your Travis configuration file.
|