// Notes from our previous deploy strategy
Using
ember-cli-deploy
we will deploy our Ember(-cli) app to S3 (and cloudfront), Redis via github and codeship.
Since skill-set's may vary, set's start by breaking this down at a high level:
This is a CI (continuous deployment setup. Every time we push certain branches to github, this will trigger a deployment
What happens in deployment
- Codeship detects that we pushed to github and sets up our build environment
- First, it builds our ember app for production (or whatever environment we pass in)
- Next, it pushes
dist/index.html
to our RedisToGo- This is served from an app we'll setup on Heroku as the main page to our site
- Every other asset will be served from Cloudfront (a CDN front for our AWS S3 bucket)
Our App Heroku— will have a simple Sinatra app (there are node alternatives if you are in to that) running that grabs our most recently deployed index.html
from Redis.
RedisToGo— This is our hosted redis database that's attached to our sinatra app and where our deployment launches index.html
.
Cloudfront (via S3)— Cloudfront will act as our CDN for a AWS S3 bucket that contains all of our application assets.
Working together— Users will hit our Heroku app, which will serve up our index.html
from Redis. Inside of that index.html
, all of the assets will point to Cloudfront.
Run our ember app locally
I've thrown together a demo project that have a few features to help us make sure our setup works:
- Different routes, so we can test visiting more than just the root
/
- Stylesheets, so we can make sure our assets are pulling in properly as well
- A few tests so we can make sure they run when we push
You can grab a copy of the project here without and of the deploy steps done.
Now we'll setup our otherwise generic Ember App for deployment.
Install ember-cli-deploy
and the redis and s3 plugins:
# https://www.npmjs.com/package/ember-cli-deploy
npm install ember-cli-deploy --save-dev
npm install ember-deploy-redis ember-deploy-s3 --save-dev
Now, we'll try to dumbly deploy.
- Run
ember deploy
, error, no config/deploy.js- You can grab a starter
config/deploy.js
from this gist, which is based off the sample from https://www.npmjs.com/package/ember-deploy
- You can grab a starter
- Run
ember deploy
again, and credential issues (because we haven't put in any Redis or other info)
Redis is a "key-value cache and store". Give it a try if you've never messed with it: http://try.redis.io/
Before we get started, it can help to install redis locally to do some basic trouble shooting here.
- Install homebrew if you haven't already
brew install redis
Given our redis to go link, let's try to connect. First, make sure you have redis installed locally so you have access to the redis-cli
tool.
- Create heroku app
- Add resources page -> Add-ons -> Redis to go -> save
- click on the redist to go link
- Grab the url similar to: redis://redistogo:9999999999999999999@bearfish.redistogo.com:0000/
Now refernce the long link we got from redis to go to grap host, port, and password.
At this point it's critical to realize how this link needs to be treated very securly.
Given the concepts, let's make something happen here.
http://stackoverflow.com/questions/17846371/how-to-connect-to-redistogo-how-to-see-the-data
# redis://redistogo:9999999999999999999@bearfish.redistogo.com:0000/
redis-cli -h bearfish.redistogo.com -p 0000 -a 9999999999999999999
- Clone the reader (Sinatra app)
- Bundle
- Change environment variables
- connect to redis and add
Get something out of Reids on the localhost
- add to your local repo
heroku git:remote -a orgname-reponame -r orgname-reponame
- push
- Add config varaibles
heroku config:add REDISTOGO_URL=redis://redistogo:9999999999999999999@bearfish.redistogo.com:0000/ PROJECT_NAME=projectname --app reponame
- Visit the http, and there you see your sample text from the last section!
Now it's time to hook it up to our ember deploy.
Deploy redis from Ember
-
Update
config/deploy.js
-
install node dotenv, and add the loader npm install dotenv --save
-
make your dot env file require('dotenv').load();
-
deploy
-
log in to redistogo to look at the list of keys
-
show that you get the index.html page from redis to go
-
also
heroku open
to show you get the correct index.html
Now that we have our index page deploying correctly, the next big issue is getting AWS setup right. This is a painful process, so hang in there.
Sign into your AWS account, log into the AWS console, and then go to S3.
We'll create a bucket to hold everything except index.html
.
For a lot of the steps here I followe a great article: http://kerrygallagher.co.uk/deploying-an-ember-cli-application-to-amazon-s3/
-
Create new bucket Console -> S3 -> Create bucket -> [name bucket]
-
Create special user for bucket, as to keep permissions well scoped
services -> IAM. Users -> Create new users
I'll call mine ember-deploy. Make sure to save the acces key id and secret access key.
-
Next, assign IAM policy to user
ember-deploy
{
"Statement": [
{
"Action": "s3:*",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<ASSETS BUCKET NAME>",
"arn:aws:s3:::<ASSETS BUCKET NAME>/*",
]
}
]
}
-
Next, assign bucket properties to allow world-writability
S3 panel -> "Right click bucket" -> properties -> permissions -> Add bucket policy
{
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET NAME>/*"
}
]
}
Ok, so let's plug in our keys into our deploy.js
.
Access Key ID: 000000000000000000 Secret Access Key: 0000000000000000000000000000000000
S3_ACCESS_KEY_ID=000000000000000000
S3_SECRET_ADDESS_KEY=0000000000000000000000000000000000
IRL: I use transmit instead of the S3 interface. If you use transmit at all, do it.
Error I was getting:
Unable to sync: PermanentRedirect: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
Use "region": "us-west-2"
, or whatever that is, to indicate. Here's where you can find all the things: http://docs.aws.amazon.com/general/latest/gr/rande.html
ember deploy:assets
sanity check one: Look at data on S3 to make sure it's coming through
sanity check #2 access stuff from web.
Now let's cleanup our buckets by specifying which prefix bucket name we are using: "prefix": "production"
wipe out all uploaded files, and upload again
ember deploy:assets --environment=development
ember deploy:assets --environment=production
ember deploy:assets --environment=staging
AWS -> Cloudfront
Setp1: Select Deliver Method web
Setp 2: Create a distribution Origin Domain Name: www.domain.com.s3.amazonaws.com Origin Path: /staging Oriding ID: (I just leave it) (I also didn't restrict bucket access)
Which Gives Us Domain: .cloudfront.net
Currently, our assets (from our sinatra app) point to the ether. We need to fingerprint them for use with cloudfront
in brocfile,
var app = new EmberApp({
fingerprint: {
prepend: '<cloudfront-id-thingy>.cloudfront.net'
}
});
All is well, right? Nope.
From the ember cli docs, here's my solution.
/* global require, module */
require('dotenv').load();
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
// This is all to set the correct CDN per environment
var env = EmberApp.env() || 'development';
var isProductionLikeBuild = ['production', 'staging'].indexOf(env) > -1;
var asset_arg = 'ASSETS_PREPEND_PATH_' + env.toUpperCase();
var prepend_path = env ? process.env[asset_arg] + '/' : '';
var app = new EmberApp({
fingerprint: {
enabled: isProductionLikeBuild,
prepend: prepend_path
},
sourcemaps: {
enabled: !isProductionLikeBuild
},
minifyCSS: { enabled: isProductionLikeBuild },
minifyJS: { enabled: isProductionLikeBuild },
tests: process.env.EMBER_CLI_TEST_COMMAND || !isProductionLikeBuild,
hinting: process.env.EMBER_CLI_TEST_COMMAND || !isProductionLikeBuild,
});
module.exports = app.toTree();
http://treyhunner.com/2015/03/deploying-an-ember-cli-application-via-ssh/
From trey's blog $ export tag="example:$(git rev-parse --short HEAD)" $ ember deploy:activate --revision $tag --environment production
[setup commands]
npm install -g codeclimate-test-reporter
npm install -g ember-cli bower phantomjs
bower install --quiet
npm install
touch .env
[Configure Test Pipelines]
# This is blowing up on staging and working find on local
# Troubleshooting (4/2)
ember test
# use the magic of sed to replace "dashboard/" with ""
# yey! blanket fixed this... sed -i.bak 's/SF:dashboard/SF:./g' lcov.info
#if [ "$CI_BRANCH" == "develop" ]; then CODECLIMATE_REPO_TOKEN=0000000000000000 codeclimate < lcov.info; fi
#ember deploy --environment=production
#export tag="dashboard:$(git rev-parse --short HEAD)"
#ember deploy:activate --revision=$tag --environment=production
#ember deploy:list --environment=production
All the .env
variables
Post slack webhook