For development on just the server / serverless part of the application, you just need the usual.
$ git clone https://github.com/FormidableLabs/badges.git
$ cd badges
$ yarn install
Then start the server:
$ yarn start
# OR, full debug + pretty logging
$ DEBUG="badges:*" yarn start:dev
And try out some sample URLs that don't need additional config:
- http://127.0.0.1:3000/size/github/FormidableLabs/react-fast-compare/master/index.js
- http://127.0.0.1:3000/size/npm/victory/dist/victory.min.js?gzip=true
- http://127.0.0.1:3000/browsers?firefox=20,26&iexplore=!8,-9,10
Some of our API calls utilize secrets stored in AWS as part of the deployment process. You can still develop against these by using your appropriate AWS credentials along with the same start task:
$ AWS_REGION=<INSERT_REGION> \
aws-vault exec <INSERT_AWS_VAULT_PROFILE> --no-session -- \
yarn start
# Could look something like
$ AWS_REGION=us-east-1 \
aws-vault exec jane.developer --no-session -- \
yarn start
(You can provide normal AWS environment variables / local config files for credentials as an alternative, but we recommend aws-vault
due to the enhanced security of credential use and storage.)
Then try out things like:
- http://127.0.0.1:3000/travis/infernojs/inferno/sauce/Havunen?name=InfernoJS
- http://127.0.0.1:3000/sauce/Havunen?labels=none
The infrastructure for this project is automated through CI/CD. Pull requests receive comments when they pass CI that give links to both a PR preview environment and to CodePipeline for manually approving production deploys.
The project uses GitHub Flow. After testing an artifact in a PR environment, we deploy that same artifact to production from the branch rather than from merge to master
. It's important to be aware that an artifact built from master
post-merge may not be exactly the same as the artifact deployed from the branch.
We use "support tiers" for managing resources shared across PR environments and for emulating multi-account isolation of prod
and nonprod
via IAM in a single account. These "tiers" are the only manual setup required to launch this project. In the future, we may support, and migrate to, multiple AWS accounts.
terraform/admin
: Controls the underlying infrastructure for the other TF infrastructures in automation, and consequently is the only one that you'll need to manually change from a local machine to get everything up and running.terraform/app
: Controls the application support resources like CDN, domain name, etc. Modifications handled by automation.terraform/cd
: Controls the application deployment pipeline like CodeBuild, artifacts, etc. Modifications handled by automation.
Our infrastructures all coalesce around some common configurations that we pass on the command line through environment variables:
SERVICE_NAME
: Name of the application itself. In our use for this project, it's alwaysbadges
.TIER
: Name of the conceptual tier ofterraform/admin
control. We usenonprod
for things like developer sandboxes and our per-pull-request temporary environments. We useprod
for the production environment.ℹ️ Note: For the
terraform-aws-serverless
module we use to control Serverless Framework application privileges, we mapTIER
to thestage
input and then use a wildcard to map our use ofTIER-STAGE
for least-privileged IAM construction.STAGE
: Unused interraform/admin
. Forterraform/app
andterraform/cd
, this is a unit of separate stage to support things like per-pull-request environments likepr123
.
Putting this all together, in nonprod
environment you will see infrastructures like badges-nonprod-pr123
. In production, you will see infrastructures like badges-prod-production
as production
is hard-coded for STAGE
.
For our AWS tagging and resource groups, we use a slightly different scheme to comport with how the terraform-aws-serverless
module tags things:
Service
:SERVICE_NAME
. E.g.,badges
Tier
:TIER
. E.g.,nonprod
Stage
: AlsoTIER
as that is what goes into theterraform-aws-serverless
E.g.,nonprod
TierStage
: A custom extra field to map to our use ofSTAGE
. E.g.,pr123
for a per-PR environment orproduction
for production.
If you are creating/modifying the terraform/admin
infrastructure from your machine, you'll need:
-
tfenv to get a compliant version of
terraform
:$ brew install tfenv $ cd PATH/TO/badges $ tfenv install # Confirm version matches value in `.terraform-version` $ terraform --version Terraform v0.12.10
-
terragrunt installed without dependencies
$ brew install --ignore-dependencies terragrunt $ terragrunt --version
This section is for the initial setup and modification of a given TIER
for terraform/admin
configurations.
ℹ️ Note: If you need to modify infrastructures in
terraform/{app,cd}
just edit the files and open a pull request. All the changes are taken care of automagically in automation!
-
Set up your AWS credentials. We recommend aws-vault.
-
(For Formidables for this project) Ask
@tptee
or@ryan-roemer
for AWS, Fastly, Sauce, and Github credentials. You'll need 1password access for the following:FASTLY_API_TOKEN
: IC vault.Fastly (Formidable)
>TOKENS
>badges (FASTLY_API_TOKEN)
. Namedterraform
in Fastly admin console.SAUCE_ACCESS_KEY
: IC vault.Sauce Labs
>KEYS
>SAUCE_ACCESS_KEY
.GITHUB_TOKEN
: IC vault.GitHub (badges-ci)
>TOKENS
>CI (GITHUB_TOKEN)
. Namedbadges-ci
in GitHub web console.
-
Create/update the nonprod tier with the below command (assuming using
aws-vault
, if not remove line):# (OPTIONAL) Check your changes first $ FASTLY_API_TOKEN=<REDACTED> \ SAUCE_ACCESS_KEY=<REDACTED> \ GITHUB_TOKEN=<REDACTED> \ SERVICE_NAME=badges \ TIER=nonprod \ aws-vault exec <SUPERADMIN> --no-session -- \ terragrunt plan --terragrunt-working-dir terraform/admin # Go do it! $ ... <ALL THE SAME STUFF FROM ABOVE> ... terragrunt apply --terragrunt-working-dir terraform/admin
-
Create/update the prod tier by repeating the previous command with
TIER=prod
. -
Open a pull request and watch the magic happen for the rest of the infrastruction and application pieces!
Releasing entails deploying the application AWS artifact all the way to production via a pull request, then adding version tags to git.
As an application developer, everything you need to take a pull request all the way to production is managed via automation in each pull request!
- Log in to the appropriate AWS account.
- Open a pull request and wait for the CI check to complete.
- When CI completes, it posts a comment with links to the PR environment and the deployment pipeline. Verify your changes in the PR environment, then click the link to the pipeline page.
- On the pipeline page, you'll see an approval step for deploying to production. Click "Review" and then "Approve" in the modal that pops up.
- After the pipeline deploys to production, it posts a link to production in the PR. Verify your changes in prod.
- Merge the pull request!
ℹ️ Note: If multiple pull requests are open, each separate branch must be up-to-date with
master
with CI passing before a merge is possible. We implement this via GitHub protected branches. Pull requests are blocked once a branch is out-of-date frommaster
, requiring human intervention to catch up a branch and push changes (which will then trigger CI to rebuild the artifact and re-deploy the per-PR application). As a helpful tip, GitHub's pull request interface provides anUpdate branch
button when it detects skew frommaster
, which may work for an easier developer experience.The motivation for this restriction is that we use a Serverless application artifact generated in a per-PR environment directly as the new "production" via our CodeBuild pipeline. If multiple PRs are open, after one is promoted and merged, then the other branches in open PRs could be missing important changes when next promoted to production. Our protected branch approach entails a little more work for each open pull request, but this approach (1) guarantees new production artifacts are always correct and up to date with
master
, and (2) we avoid the "thundering herd" problem of auto-rebuilding all open PRs when one is merged by pushing manual, lazy work to PR authors.
Only for Formidables / project maintainers.
We should publish a tagged version to GitHub on every release / update:
- Update
CHANGELOG.md
, following format for previous versions - Commit as "Changes for version NUMBER"
- Run
npm version patch
(orminor|major|VERSION
) to run tests and lint, build published directories, then updatepackage.json
+ add a git tag. - Run
git push && git push --tags