AWS Code Deploy

Solano CI integrates with CodeDeploy to seamlessly deploy your application to your CodeDeploy-managed servers on a passing CI build.

Once your build has passed its tests, Solano CI will execute a script you supply to prepare your application for release, use the aws deploy push command to package and push your app to CodeDeploy, and then optionally deploy the app revision to an CodeDeploy Deploy Group and confirm that it’s been deployed.

Setting up automatic CodeDeploy deployment from your Solano CI build involves 2 steps:

  1. Define your solano.yml configuration
  2. Set environment variables with AWS credentials for an IAM user authorized to perform CodeDeploy deployments

By default, Solano CI will read your CodeDeploy AppSpec and package up the repo directory. You can optionally:

  1. Write a script that prepares a directory with your app to be packaged and pushed
  2. Write a script that generates an CodeDeploy AppSpec

Step-by-Step Setup

Step 1: Configure CodeDeploy Deployment For Solano CI

To enable CodeDeploy deployment from your Solano CI build, all you need to do is define a deploy section in your solano.yml (or tddium.yml) with amazon parameters.

There are 3 required configuration keys within the amazon parameters:

1. application_name: (REQUIRED) The application name to push to, as it appears in your management console.

2. app_spec_template (or app_spec_generator): (one of two is REQUIRED) app_spec_template is the path to the appspec file to use. If you need to generate the appspec based on build parameters, you can instead supply the path to an app_spec_generator script that emits an appspec.yml file. Either way, the appspec will be copied into application staging directory.

3. deploy_mapping: (REQUIRED) Map that defines branch and action to be made:

  • branch: branch name, can be simple string or include * to match any number of characters.
  • action: Accepts three values:
    • gen-image: simply runs app_spec and application generators, useful for debugging.
    • publish: generates image and publishes to S3 storage.
    • deploy: generates image, publishes to S3 storage and deploys.
  • deployment_group: For complete push+deploy flows, the name of the deployment group to which the newly pushed app revision should be deployed (applicable only for deploy action).
  • revision: a path specification, passed directly to aws deploy push indicating where to put the new app revision. Should be in following format: {"revisionType":"S3","s3Location":{"bucket":<...>,"bundleType":<...>,"key":<...>}}'.

As it’s required by aws deploy sub-command (–revision option). You can use :branch and :revision and :session_id place holders that are replaced by branch name, latest commit id and session id respectively. Additionally, :timestamp_utc and :date_utc can be used to include UTC time and date stamps corresponding with when Solano CI builds were initially triggered. If for some reason you don’t want to replace those placeholders, you should add one more : before it, additional : is removed from final file name. Example: "key": ":branch::revision" is converted to "key": "master:revision".

Beyond these 3, there are two optional keys:

4. application_generator: (OPTIONAL) a script you supply that Solano CI will run before uploading to S3 that prepares the application directory referenced by your appspec.yml file. Solano CI will copy whole repo if application_generator isn’t defined.

5. deployment_config_name: (OPTIONAL) deployment configuration name. Default value is CodeDeployDefault.OneAtATime.

The basic configuration with app_spec_template only, that packages up the repo directory unmodified:

# solano.yml
... existing configuration ...
environment:
  AWS_DEFAULT_REGION: us-east-1 # or whatever you need
deploy:
  amazon:
    application_name: SimpleApp
    app_spec_template: deploy/appspec.yml
    deploy_mapping:
      - branch: default_actions
        action: publish
        revision: '{"revisionType":"S3","s3Location":{"bucket":"solano-codedeploy","bundleType":"zip","key":"DefaultActions.tgz"}}'

To perform more complicated pre-deploy actions, like post-processing assets before packaging, supply app_spec_generator and application_generator:

# solano.yml
... existing configuration ...
environment:
  AWS_DEFAULT_REGION: us-east-1 # or whatever you need
deploy:
  amazon:
    app_spec_generator: deploy/app_spec_generator
    application_name: SimpleApp
    application_generator: deploy/application_generator
    deploy_mapping:
    - branch: master
      action: deploy
      deployment_group: SimpleDG
      revision: '{"revisionType":"S3","s3Location":{"bucket":"solano-codedeploy","bundleType":"zip","key":"TestApp.zip"}}'
    - branch: publish_*
      action: publish
      revision: '{"revisionType":"S3","s3Location":{"bucket":"solano-codedeploy","bundleType":"zip","key":"TestApp-:session_id.zip"}}'

For more information about scripted appspec and revision package generation, see Scripted Generation of your AppSpec and Scripted App Directory Preparation.

Step 2: Configuring Credentials

We strongly recommend against checking in your AWS key pairs into source control. Solano CI supports setting ephemeral environment variables using the solano CLI. read more.

You should set the following keys:

  • AMAZON_DEPLOY_AWS_ACCESS_KEY_ID
  • AMAZON_DEPLOY_AWS_SECRET_ACCESS_KEY

Note that the key pair you use here must correspond to a user or IAM role that has at least the following capabilities.

  1. s3:GetObject
  2. s3:PutObject
  3. codedeploy:*.; more restrictive capabilities may be sufficient here depending on your use case.

Detailed Deployment Flow

Solano CI’s integration will perform the following exact steps after a build has passed its tests. If any step fails (exits non-zero) the process will halt.

1. Run the $app_spec_generator <app_spec_dir> command that you implement. Output logged to deploy-amazon-appspec_generator0.log

2. Run the $application_generator <app_spec_dir> <app_dest_dir> command that you implement. Output logged to deploy-amazon-application_generator0.log.

3. Read the AMAZON_DEPLOY_AWS_ACCESS_KEY_ID and AMAZON_DEPLOY_AWS_SECRET_ACCESS_KEY environment variables for credentials for the next step.

4. (If action is publish or deploy) Runs a Solano-provided program that will invoke tar or zip commands depending on bundleType. Than upload created archive: aws s3api put-object --bucket $bucket --key $key --body $file. At the end it registers revision: aws deploy register-application-revision --application-name $application_name --description 'Uploaded by SolanoLabs session $session_id at $now' --revision $revision. Output logged to deploy-amazon-prepare_revision0.log.

5. (If action is deploy) Runs a Solano-provided program that will invoke aws deploy create-deployment to the configured deploy group, and then poll with aws deploy get-deployment to wait until the deployment has succeeded. Output logged to deploy-amazon-deployment0.log.

Scripted Generation of your AppSpec

Solano CI will execute the bash script you specify in the app_spec_generator key to produce the appspec.yml file used by the aws deploy commands it will execute.

The script will be invoked with a single command line argument: the name of the directory in which it should write appspec.yml.

An example script:

#!/usr/bin/env bash
cd $1
echo "version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/deploy
hooks:
  BeforeInstall:
    - location: scripts/install_dependencies
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/start_server
      timeout: 300
      runas: ec2-user
  ApplicationStop:
    - location: scripts/stop_server
      timeout: 300
      runas: root

" > appspec.yml

echo 'Application Specification file is generated.'

The output of the app_spec_generator command will be attached to the build report as deploy-amazon-appspec_generator0.log.

If the app_spec_generator fails (exits non-zero), the deployment process will not complete.

If you’d like to control the contents of the AppSpec based on parameters from the current build, like the fact that it’s running in CI, or the branch name or information from commit messages, you can implement that logic however you need and configure Solano CI to call it as part of the automated deploy.

Scripted App Directory Preparation

Solano CI will invoke the application_generator command you specify to prepare a directory containing ready-to-release application assets that will later be turned into an Revision.

The script will be invoked with 2 arguments: the directory containing the appspec.yml and the target directory into which the application assets should be written.

An example script that copies app assets from a Template directory into the destination specified by Solano CI:

#!/usr/bin/env bash

APP_SPECS_FOLDER=$1
DEST_APP_FOLDER=$2

SCRIPT=$(readlink -f $0)
SCRIPTPATH=`dirname $SCRIPT`

TEMPLATE_DIR=${SCRIPTPATH}/Template

echo 'Copy template into app directory'
cp -r ${TEMPLATE_DIR}/* $DEST_APP_FOLDER

echo 'Copy generated AppSpecs files'
cp -r ${APP_SPECS_FOLDER}/* ${DEST_APP_FOLDER}

echo 'Done'

The output of the app_spec_generator command will be attached to the build report as deploy-amazon-application_generator0.log.

Note

Solano CI modifies or adds certain files to ruby/rails repos to better collect results from our parallel test runners (typically config/boot.rb and various config/*.yml files). Before deploying your code, you may want to revert these changes with a command like git reset --hard $TDDIUM_CURRENT_COMMIT in a post_build setup hook.