Skip to content

ember-cli-deploy/ember-cli-deploy-s3-index

Repository files navigation

ember-cli-deploy-s3-index Build Status Build status

An ember-cli-deploy plugin to deploy ember-cli's bootstrap index file to S3.

This plugin uploads a file, presumably index.html, to a specified S3-bucket.

More often than not this plugin will be used in conjunction with the lightning method of deployment where the ember application assets will be served from S3 and the index.html file will also be served from S3.

What is an ember-cli-deploy plugin?

A plugin is an addon that can be executed as a part of the ember-cli-deploy pipeline. A plugin will implement one or more of the ember-cli-deploy's pipeline hooks.

For more information on what plugins are and how they work, please refer to the Plugin Documentation.

Quick Start

To get up and running quickly, do the following:

$ ember install ember-cli-deploy-s3-index
  • Place the following configuration into config/deploy.js
ENV['s3-index'] = {
  accessKeyId: '<your-access-key>',
  secretAccessKey: '<your-secret>',
  bucket: '<your-bucket-name>',
  region: '<your-bucket-region>'
}
  • Run the pipeline
$ ember deploy

ember-cli-deploy Hooks Implemented

For detailed information on what plugin hooks are and how they work, please refer to the Plugin Documentation.

  • configure
  • upload
  • activate
  • fetchRevisions

Configuration Options

For detailed information on how configuration of plugins works, please refer to the Plugin Documentation.


**WARNING: Don't share a configuration object between [ember-cli-deploy-s3](https://github.com/ember-cli-deploy/ember-cli-deploy-s3) and this plugin. The way these two plugins read their configuration has sideeffects which will unfortunately break your deploy if you share one configuration object between the two** (we are already working on a fix)

accessKeyId

The AWS access key for the user that has the ability to upload to the bucket. If this is left undefined, the normal AWS SDK credential resolution will take place.

Default: undefined

secretAccessKey

The AWS secret for the user that has the ability to upload to the bucket. This must be defined when accessKeyId is defined.

Default: undefined

profile

The AWS profile as definied in ~/.aws/credentials. If this is left undefined, the normal AWS SDK credential resolution will take place.

Default: undefined

bucket (required)

The AWS bucket that the files will be uploaded to.

Default: undefined

region (required)

The region your bucket is located in. (e.g. set this to eu-west-1 if your bucket is located in the 'Ireland' region)

Default: undefined

prefix

A directory within the bucket that the files should be uploaded in to.

Default: ''

filePattern

A file matching this pattern will be uploaded to S3. The active key in S3 will be a combination of the bucket, prefix, filePattern. The versioned keys will have revisionKey appended.

Default: 'index.html'

acl

The ACL to apply to the objects.

Set to false to not apply any ACLs.

Default: 'public-read'

cacheControl

Sets the Cache-Control header on uploaded files.

Default: 'max-age=0, no-cache'

distDir

The root directory where the file matching filePattern will be searched for. By default, this option will use the distDir property of the deployment context.

Default: context.distDir

revisionKey

The unique revision number for the version of the file being uploaded to S3. The key will be a combination of the keyPrefix and the revisionKey. By default this option will use either the revision passed in from the command line or the revisionData.revisionKey property from the deployment context.

Default: context.commandOptions.revision || context.revisionData.revisionKey

allowOverwrite

A flag to specify whether the revision should be overwritten if it already exists in S3.

Default: false

s3Client

The underlying S3 library used to upload the files to S3. This allows the user to use the default upload client provided by this plugin but switch out the underlying library that is used to actually send the files.

The client specified MUST implement functions called getObject and putObject. See [Using V2 API] (https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html#using_v2_commands).

Default: the default S3 library is @aws-sdk/s3-client (AWS JS SDK v3). Please use this addon version < 3.0.0 if you want to use AWS JS SDK 2.0

endpoint

AWS (or AWS compatible endpoint) to use. E.g. with DigitalOcean Spaces, Microsoft Azure Blob Storage, or Openstack Swift

If endpoint set the region option will be ignored.

Default: [region].s3.amazonaws.com

serverSideEncryption

The Server-side encryption algorithm used when storing this object in S3 (e.g., AES256, aws:kms). Possible values include:

  • "AES256"
  • "aws:kms"

urlEncodeSourceObject

Controls if the x-amz-copy-source header is going to be be URL encoded. There is a known issue with DigitalOcean Spaces and older versions of CEPH that don't accept URL encoded copy sources.

If you are using DigitalOcean spaces you need to set this setting to false.

Default: true

didDeployMessage

A message that will be displayed after the index file has been successfully uploaded to S3. By default this message will only display if the revision for revisionData.revisionKey of the deployment context has been activated.

Default:

if (context.revisionData.revisionKey && !context.revisionData.activatedRevisionKey) {
  return "Deployed but did not activate revision " + context.revisionData.revisionKey + ". "
       + "To activate, run: "
       + "ember deploy:activate " + context.revisionData.revisionKey + " --environment=" + context.deployEnvironment + "\n";
}

How do I activate a revision?

A user can activate a revision by either:

  • Passing a command line argument to the deploy command:
$ ember deploy --activate=true
  • Running the deploy:activate command:
$ ember deploy:activate --revision <revision-key>
  • Setting the activateOnDeploy flag in deploy.js
ENV.pipeline = {
  activateOnDeploy: true
}

What does activation do?

When ember-cli-deploy-s3-index uploads a file to S3, it uploads it under the key defined by a combination of the four config properties bucket, prefix, filePattern and revisionKey.

So, if the filePattern was configured to be index.html and there had been a few revisons deployed, then your bucket might look something like this:

$ aws s3 ls s3://<bucket>/
                           PRE assets/
2015-09-27 07:25:26        585 crossdomain.xml
2015-09-27 07:47:42       1207 index.html
2015-09-27 07:25:51       1207 index.html:a644ba43cdb987288d646c5a97b1c8a9
2015-09-27 07:20:27       1207 index.html:61cfff627b79058277e604686197bbbd
2015-09-27 07:19:11       1207 index.html:9dd26dbc8f3f9a8a342d067335315a63

Activating a revision would copy the content of the passed revision to index.html which is used to host your ember application via the static web hosting feature built into S3.

$ ember deploy:activate --revision a644ba43cdb987288d646c5a97b1c8a9

When does activation occur?

Activation occurs during the activate hook of the pipeline. By default, activation is turned off and must be explicitly enabled by one of the 3 methods above.

Prerequisites

The following properties are expected to be present on the deployment context object:

Configuring Amazon S3

Minimum S3 Permissions

This plugin requires the following permissions on your Amazon S3 access policy:

  • For the bucket:
    • s3:ListBucket
  • For the files on the bucket:
    • s3:GetObject
    • s3:PutObject
    • s3:PutObjectAcl

The following is an example policy that meets these requirements:

{
    "Statement": [
        {
            "Sid": "Stmt1EmberCLIS3IndexDeployPolicy",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<your-bucket-name>",
                "arn:aws:s3:::<your-bucket-name>/*"
            ]
        }
    ]
}

Using History-Location

You can deploy your Ember application to S3 and still use the history-api for pretty URLs. This needs some configuration and the exact process depends on whether or not you are using Cloudfront to serve cached content from your S3 bucket or if you are serving from an S3 bucket directly using S3's Static Website Hosting option. Both options work, however, the Cloudfront method allows the process to occur without flashing a non-pretty URL in the browser before the application loads.

With Cloudfront

A Cloudfront Custom Error Response can handle catching the 404 error that occurs when a request is made to a pretty URL and can allow that request to be handled by index.html and in turn Ember.

A Custom Error Response can be created for your CloudFront distrubution in the AWS console by navigating to:

Cloudfront > Distribution ID > Error Pages > Create Custom Error Response.

You will want to use the following values.

  • HTTP Error Code: 404: Not Found
  • Customized Error Response: Yes
  • Response Page Path: /index.html
  • HTTP Response Code: 200: OK

Without Cloudfront


**WARNING: ⚠️ This solution might not work in all browsers. See [this issue](#68) for details.

From within the Static Website Hosting options for your S3 bucket, you can use S3's Redirection Rules-feature to redirect user's to the correct route based on the URL they are requesting from your app:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName><your-bucket-endpoint-from-static-website-hosting-options></HostName>
            <ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

Previewing Revisions

If you'd like to be able to preview a deployed revision before activation, you'll need some additional setup. See this article for more information.

Running Tests

  • npm test