# Deployment
For information on the command line interface, please run litexa deploy --help
.
Now that you have a Litexa project generated and working, it is time to deploy it as an Alexa skill. Deploying your skill is how you can see it in action on a real Alexa-enabled device like an Echo, or, if you don't have access to one, the ASK Developer Console.
Let's take a look at your Litexa config again. It probably looks something like this:
{
"deployments": {
"development": {
"module": "@litexa/deploy-aws",
"s3Configuration": {
"bucketName": "suncoast-assets"
},
"askProfile": "suncoast",
"awsProfile": "prototyping"
}
}
}
You will see that there is a key called development
under the deployments
key. This is called a
deployment target. A deployment target is a named
configuration for the deployment of your skill. It determines where, how, and with what settings a
skill will be deployed.
You can name your deployment targets whatever you want and have as many as you want. The development
target is just the one litexa generate
creates for you to get started.
Why would I want multiple deployment targets?
The purpose of multiple deployment targets is to allow multiple copies of a skill to
exist at the same time. Each deployment target produces its own isolated skill, independent of
other skills. You may want to use multiple deployment targets to mark stages of your
skill development. For example, you might use the development
target for active skill development
and adding features. You might then have a beta-test
target that you share with beta testers (opens new window) so that you can get feedback from potential customers. And finally, you will probably have a
production
target for your public,
customer-facing skill in the Alexa Skill Store.
Wait a minute, what do you mean by where a skill will be deployed?
A skill has to live somewhere for it to be accessed. Think of the Alexa-enabled device as a messenger between your user and your skill. The user says something to their Echo. The Echo passes that message to its backend, which transforms it into a request to invoke your skill. The backend then sends that request to wherever your skill lives, much like how a web browser fetches the contents of a website the user requested.
More specifically, Alexa skill deployment is composed of 2 parts. The first part is deployment of your skill logic, or backend deployment. The second is your Alexa Skills Kit (ASK) information - what Alexa needs to know about to build and publish your skill to the Skill Store. This comprises of your skill model, manifest file, skill ID, and if it exists, monetization metadata.
Going back to your Litexa config, you'll notice that within a deployment target, there is a module
field. This field indicates the name of the node module your Litexa skill will use for its backend
deployment. The module implements what sort of hosting, persistent data storage, and logging your
skill code will use during execution. At this time, there is one official deployment module called
@litexa/deploy-aws
, which is already set in the Litexa config for your convenience. Meanwhile,
Litexa itself performs the second part for you.
Let's talk about each of these two deployment parts in turn.
# Litexa Deploy AWS
This module implements Litexa deployment to Amazon Web Services, with the following structure:
- Assets are copied into a new or existing S3 bucket of your choice
- Permanent data store is written to a new DynamoDB table
- Skill endpoint is hosted in a Lambda
- Logging is directed to Cloudwatch
# Installation
Run
npm install -g @litexa/deploy-aws
to install this package side by side with
your litexa package. This will then let you specify
@litexa/deploy-aws
as a deployment module in any
of your projects.
# Authorization
AWS access is piped through the aws-sdk module (installed as a @litexa/deploy-aws
node_module dependency), so all of its configuration mechanisms are supported
, e.g. setting environment variables.
The simplest way to authorize AWS is to complete the aws-cli
installation, and then use the profile name you set up
in the awsProfile
field in your Litexa config.
See: Installing the AWS CLI (opens new window) for more information.
You can alternatively provide credentials local to a particular project
by creating a aws-config.json
file in your project root containing
the following credentials:
{
"development": {
"accessKeyId": "someAccessKeyId",
"secretAccessKey": "theSecretAccessKeyForThatAccessKeyId",
"region": "us-east-1"
}
}
where development
is the name of the deployment target you want this configuration
for.
Implementation detail: If you have neither an awsProfile
field in your Litexa config
nor a local aws-config.json
file, @litexa/deploy-aws
will attempt to use the
aws-cli profile named default
.
WARNING
Bear in mind you want to keep your aws-config file local though,
you don't want to be sharing that with other people! We've generated a .gitignore
for you that includes it, but if you use a different source code sharing
solution, you may want to configure prevention on uploading this file.
Diving Deeper on AWS Security
In the long run, it will be beneficial to follow secure credential management guidelines. For a starting point on what AWS security credentials are, you can begin here (opens new window). For secure AWS credential management, you may consider reading Best Practices for Managing AWS Access Keys (opens new window) and IAM User-specific Credential Management (opens new window).
There is one more thing you need to set up for authorization, and that is permissions. AWS permissions are bundled together in what's called a policy. A policy is then attached to your IAM user, which is the credentials that get used for deployment. To get that set up, go to the AWS Permissions section.
# AWS Configuration
The @litexa/deploy-aws
module requires you to fill out one more field in your litexa
config called s3Configuration
. There are also some optional lambdaConfiguration
parameters you can put into your configuration for further project customization.
# S3 Configuration
The deploy module uses S3 to host your skill's assets, which can be sounds and images.
Assets are deployed to the S3 bucket (opens new window) specified by
s3Configuration.bucketName
in your Litexa config.
If this bucket doesn't exist yet, the module will automatically create it for you. If you create your own bucket:
The bucket itself does not need to be marked public. Individual files will be marked public on upload.
The bucket does need to have default CORS correctly configured. See: Cross-Origin Resource Sharing (CORS) (opens new window)
# Upload Parameters
You can specify S3 upload parameters to groups of your assets by utilizing the
optional s3Configuration.uploadParams
object list.
A Litexa config that utilizes s3Configuration.uploadParams
might look like:
const deploymentConfiguration = {
name: 'my-skill',
deployments: {
production: {
module: '@litexa/deploy-aws',
s3Configuration: {
bucketName: 'my-skill-bucket',
uploadParams: [
{
filter: ['*.mp3'],
params: {
// check for file change every 10 minutes
// (useful for content files that are regularly updated)
CacheControl: 'max-age=600'
}
},
{
filter: ['*.jpg', '*.png'],
params: {
// always check for file change
// (useful during development)
CacheControl: 'no-cache'
}
},
{
params: {
// no file filter -> applies 1 hour age
// to all files that aren't caught by the
// above 2 filters
CacheControl: 'max-age=3600'
}
}
]
}
}
}
}
# S3 Configuration Schema
The schema for the s3Configuration
object is as follows:
bucketName
- (String)- The name of the bucket that your assets are deployed to.
uploadParams
- (Array<Object>) - Optionalfilter
- (Array<String>) - Optional- A list of glob patterns that, when matched to your assets,
the upload params are applied to.
- Litexa uses the minimatch NPM package (opens new window) to implement the file pattern matching.
- A list of glob patterns that, when matched to your assets,
the upload params are applied to.
params
- (Object)- An object that is passed into Litexa's call on
the AWS SDK S3 Client's
#upload()
function.- To understand what keys are acceptable in the
params
object, read more about the AWS SDK S3 Client's#upload()
function in the AWS SDK docs (opens new window).
- To understand what keys are acceptable in the
- An object that is passed into Litexa's call on
the AWS SDK S3 Client's
You can define default upload params
An uploadParams
object that either has no filter
specified, or includes a
'*'
filter, will be treated as a default set of upload parameters. All
assets that do not match any other filters will use these params
.
The order of upload params matters
Any uploadParams
objects that are not default upload parameters (see above)
are applied in order. This means that individual assets will be set to use the first,
and only the first, matching filter's params
.
You may not use the Key, Body, ContentType, and ACL keys
These keys are reserved by Litexa, so you may not use them as part of an
uploadParams
object. If you attempt to use them, the Litexa deployment
process will fail.
# Asset Deployment Location
Assets will be deployed to subdirectories of your bucket, isolating
specific deployments of specific projects from each other, copying
the contents of your litexa/assets
folder to the following location:
https://s3.{REGION}.amazonaws.com/{BUCKETNAME}/{SKILLNAME}/{DEPLOYMENTTARGET}/
Use one S3 bucket across your Litexa projects
S3 bucket names are globally unique. This means that any AWS account cannot create a bucket of the same name as an existing bucket until it is deleted. Your AWS account also has a limit on the number of buckets you can create. See here (opens new window) for bucket restrictions and limitations.
Within this location, your assets will be organized by the locales in that folder,
with the assets in the top level going into the default
folder. So if you have a
Litexa project named CatsVsCucumbers
and you're deploying the development
target,
your project folder will look like this locally:
.
├── litexa
| ├── assets
| | ├── intro.mp3
| | └── introScreen.jpg
| └── languages
| └── en-GB
| └── assets
| ├── intro.mp3
| └── resultScreen.jpg
And your S3 bucket would look like this:
.
├── CatsVsCucumbers
| └── development
| ├── default
| | ├── intro.mp3
| | └── introScreen.jpg
| └── en-GB
| ├── intro.mp3
| ├── introScreen.mp3
| └── resultScreen.jpg
By default, Litexa will upload Alexa-usable files from your assets directory and
ignore any file types it does not recognize. These files must have the file extensions:
.png
, .jpeg
, .jpg
, .mp3
, .json
, or.txt
. Litexa extensions may add to that list.
Please see the section on assets for more information.
Overriding a deployment target's assets root path
You can override the skill's assets URL path, instead of using the default S3 path (location of files
deployed from litexa/assets
). This can be useful when collaborating on a project with sizable assets,
to prevent each contributor needing to upload and maintain their own copies of assets.
A deployment target can override the skill asset root path by specifying an overrideAssetsRoot
URL
in the Litexa config. For example:
const deploymentConfiguration = {
name: 'my-skill',
deployments: {
deployment_target_name: {
module: '@litexa/deploy-aws',
overrideAssetsRoot: 'https://path.com/to/your/assets/'
}
}
}
Skipping Litexa's asset reference validation
Litexa will validate asset references for certain keywords (card
, screen
, soundEffect
, etc.) and fail
Litexa tests if those assets aren't found in the litexa/assets
directory. This validation can be
disabled per deployment target, when referenced assets are missing locally (which is typically the
case when overrideAssetsRoot
is used).
A deployment target can skip asset reference validation by setting disableAssetReferenceValidation in the Litexa config. For example:
const deploymentConfiguration = {
name: 'my-skill',
deployments: {
deyployment_target_name: {
module: '@litexa/deploy-aws',
overrideAssetsRoot: 'https://path.com/to/your/assets/',
disableAssetReferenceValidation: true
}
}
}
# Lambda Configuration (optional)
The @litexa/deploy-aws
module deploys your skill to AWS Lambda. It sets a few defaults,
but you are welcome to override these settings with your own in the Litexa config. Here
is an example with all the supported Lambda configuration options:
{
"deployments": {
"development": {
"module": "@litexa/deploy-aws",
"s3Configuration": {
"bucketName": "suncoast-assets"
},
"askProfile": "suncoast",
"awsProfile": "prototyping",
"lambdaConfiguration": {
"Runtime": "nodejs10.x",
"MemorySize": 128,
"Timeout": 240,
"Environment": {
"Variables": {
"mySpecialVariable": 13
}
}
}
}
}
}
The lambdaConfiguration
object gets merged into the generated configuration
that will be used to call Lambda's updateFunctionConfiguration (opens new window).
You can use this to modify the Lambda's timeout, change the memory size, or
add your own environment variables. All sub keys are optional.
# DynamoDB TTL (optional)
Litexa has limited support for setting a Time To Live (TTL) (opens new window)
field with each database entry. This may be useful for limiting your table
data to active users by automatically deleting old user data. To set a Time To
Live specification, add the dynamoDbConfiguration
object to your Litexa config:
{
deployments: {
development: {
module: "@litexa/deploy-aws",
askProfile: "suncoast",
awsProfile: "prototyping",
dynamoDbConfiguration: {
timeToLive: {
AttributeName: "ttl", // needs to match the attribute name specified when enabling TTL
secondsToLive: 2592000 // specified in seconds (would wipe data if not updated in 30 days)
}
}
}
}
}
Litexa does not enable TTL
At this time, Litexa does not create or update your table with your TTL settings - it simply updates the specified attribute in the database records with every request. You will need to manually enable TTL (opens new window) for your table in the AWS console or AWS CLI.
You can find your skill's table name in the artifacts.json
file as part of
the dynamoDBARN
, once the skill has been deployed.
# CloudWatch Logging
Litexa uses an environment variable called loggingLevel
to determine what to log. In
this deploy module, logs are recorded in CloudWatch Logs. There are 3 possible values
you can set for this variable:
terse
: This is the default setting. Will log the relevant part of the skill request and the full skill response.verbose
: Will log the full skill request and the full skill response.- (empty string): Will not log skill requests and responses.
See the Lambda Configuration section above for how to set this variable.
If you have any logging output in your litexa project though, those will still be logged to CloudWatch independently of this setting.
You can retrieve your logs via the litexa logs
command for a specified deployment target. This will retrieve
logs after the timestamp of the command itself. The deploy module
will download your skill's CloudWatch Logs and format them as skill requests and responses. The downloaded
logs will be available in the project's .logs/{DEPLOYMENTTARGET}
directory.
Use the log command in development, not production
If your skill becomes popular, running litexa logs
may produce very large log files of requests and responses
happening in parallel. That may make it difficult to trace a single skill interaction. It may also cause a
significant performance hit while it is running. We recommend using the command for when you are testing
your skill on a device or the simulator instead.
It is safe (won't cause Litexa project issues) to delete the .logs
directory and any files within.
For more information on the log command line interface, please run litexa logs --help
.
# Local Caching of Deployment Artifacts
A deployment will use a directory named after that deployment target
inside the project's ephemeral .deploy
directory to cache intermediate
files before uploading, as well as additional files to aid in debugging
deployed artifacts.
For speed, the local cache usually doesn't validate the contents of
the .deploy
directory, and builds incremental changes on top of it.
If you have modified this directory in any way, deploy results
are undefined.
Conversely, you can safely delete each deployment target directory inside
the .deploy
directory at any time; this module will detect the cache as
empty and rebuild it as necessary. If you'd like to delete all deployment caches,
you can also just delete the .deploy
directory.
If you modify the contents of your Litexa config during
development, Litexa will automatically wipe the .deploy
and
.test
temporary directories to perform a clean deployment.
# ASK Deployment
Now that we've covered the backend deployment, we can now cover the Alexa Skills Kit (ASK) part of deployment. As a reminder, ASK deployment consist of the artifacts that Alexa needs to know about to build and publish your skill to the Skill Store.
# Authorization
Please install the ask-cli (opens new window) first and create an ASK profile associated with your Amazon developer account.
You'll notice that the Litexa config has one field we haven't discussed yet, which is the askProfile
field. Please set
that field with the name of the ASK profile you want to use for your skill.
Congrats! You are ready to deploy your skill.
You are now set to deploy your skill! If you run litexa deploy
, it will deploy the development
target of your skill. It
will go through the backend deployment first, and if it succeeds, will continue on to deploy the ASK information.
When this is complete, you can invoke your skill on an Alexa-enabled device or the skill simulator in the ASK Developer Console.
If you want to know what Litexa is doing for ASK deployment, then read on.
# Deployment Details and Artifacts
Under the hood, Litexa uses the Skill Management API, or SMAPI, to deploy your skill, using your designated askProfile
in the Litexa config. It constructs and deploys 2 ASK Developer Console artifacts for you: the skill manifest and model files.
Because it manages backend deployment separately by using the module
specified in the Litexa config, it actually does not
rely on the configured AWS profile that you may have associated with your ASK profile.
If this is your first time deploying to that deployment target, it will create a new skill for you
and save the skill ID in artifacts.json
. Note that artifacts.json
replaces the .ask/config
you would use
normally if you invoked the ask-cli directly. It is the source of your skill ID, so if you delete your skill ID,
Litexa will treat your deployment target as a new skill deployment. Otherwise, if you have a skill ID, Litexa will
update that skill.
Best Practices on Account Management
Because Litexa requires a developer account for deployment, we recommend looking at documentation for Developer Account Management (opens new window) and best practices (opens new window), especially if you are working in a team.
# Skill Manifest File
A skill manifest is your skill's metadata. It contains customer-facing information about the skill, such as the description and privacy policy, and Alexa-specific information, such as which APIs your skill needs to access. Skill developers can provide this information via a skill manifest file + SMAPI, or by filling out the information manually in the ASK Developer Console.
Litexa takes your skill.coffee/js/ts
(we might refer to this as skill.*
in documentation) and Litexa config file
to create your skill manifest file. You can find the constructed skill manifest file after a deployment
in .deploy/{yourDeploymentTarget}/skill.json
.
If you use any Litexa extensions in your project, they may add the APIs they use to your skill manifest automatically.
Otherwise, you will need to add the required fields to your skill.*
. Likewise, if you use an API Litexa does not
explicitly support (e.g. Gadget Controller), you will need to add it to your skill.*
.
# Deployment Target Overrides
If you want to change your skill manifest based on a specific deployment target, you can do so by keying the original manifest content structure on the deployment target name. This is completely optional - any unkeyed targets will fall back to using the default manifest.
For example, the below skill.js
has a different manifest for its QA
deployment target only.
const standardSkillManifest = { /* ... */ };
const qaSkillManifest = { /* ... */ };
module.exports = {
manifest: standardSkillManifest // default manifest
QA: {
manifest: qaSkillManifest // "QA" deployment target-specific manifest
}
}
# Skill Model
A custom interaction model, also referred to as a language model or skill model, is a contract that defines the voice interface your skill will accept and your customers will use, for each locale. The skill model consists of the invocation name, intents, utterances, and slots. Please see the interaction model documentation (opens new window) for definitions of these terms.
Litexa builds the skill model from your skill invocation name in the skill.*
file and the intent handlers you have
defined in your *.litexa
code by aggregating all case-sensitive unique intents and slots, and adding any required
intents for your project's litexa extensions.
It also adds the AMAZON.StopIntent, AMAZON.CancelIntent, and AMAZON.StartOverIntent intents to your model if you don't
already handle them. The Stop and Cancel intents will simply end the skill session (equivalent to END
behind
the scenes), and the Start Over intent will automatically take your skill back to its launch state (equivalent to
-> launch
behind the scenes).
Implementing these intent handlers will override these default behaviors with the additional requirements:
- for StopIntent and CancelIntent, you will need to explictly state one of the
LISTEN
controls to override the implicitEND
- for StartOverIntent, you will need to explicitly specify a new
->
transition, to replace the implicit-> launch
After a deployment, you can find the constructed model file in
.deploy/{yourDeploymentTarget}/model-{locale}.json
. For example, it may be .deploy/development/model-en-US.json
.
# Alternate Skill Invocation Name (optional)
All Alexa skills require an invocation name that users say in order to launch the skill. Invocation names are built into the skill model. These names are not unique - the Alexa-enabled device's backend determines which skill gets invoked for the user, which is opaque to both the user and skill developer. If you are developing a skill with multiple deployment targets and they all have the same invocation name, it may be difficult to know which skill was invoked when you test it.
Litexa offers configuration to change invocation names for each deployment target.
The first is an invocation
field. It maps a supported locale in your project's skill.*
to the invocation name you put in it.
The second is a invocationSuffix
field. It is a string suffix that is
automatically appended to the end of your skill invocation name.
Here's an example. Let's say your skill's invocation names in en-US and en-GB are both
cats versus cucumbers
. If you add an alternate invocation name to just en-GB in your
development
deployment target, your Litexa config will look like this:
{
"deployments": {
"development": {
"module": "@litexa/deploy-aws",
"s3Configuration": {
"bucketName": "suncoast-assets"
},
"askProfile": "suncoast",
"awsProfile": "prototyping",
"invocation": {
"en-GB": "cloudy cats"
}
}
}
}
With this setting, your skill invocation name in en-GB will be cloudy cats
while the one in
en-US will remain cats versus cucumbers
.
If you instead add an invocation suffix, your Litexa config will look like this:
{
"deployments": {
"development": {
"module": "@litexa/deploy-aws",
"s3Configuration": {
"bucketName": "suncoast-assets"
},
"askProfile": "suncoast",
"awsProfile": "prototyping",
"invocationSuffix": "dev"
}
}
}
And both locales will have the invocation name cats versus cucumbers dev
.
If you provide both fields, your skill invocation name for that locale will have both.
Combining the above examples will net you cloudy cats dev
in en-GB and
cats versus cucumbers dev
in en-US.
Once again, you can view the result skill invocation names in the deployed model files at
.deploy/{yourDeploymentTarget}/model-{locale}.json
.
# Deployment Target-based Skill Configuration
You can change the skill behavior and language model based on the deployment target you are executing tests or deploying the skill for. Please see DEPLOY variables for more information.
# Monetization
Please see the Monetization chapter.
# Switching The Persistent Store to Session Attributes Instead
While most skills usually need to store some data in between sessions, and therefore end up needing an online persistent store one way or another, some skills definitely don't need to store anything between sessions at all, and so don't need to incur any online database costs. In this case, you can switch the Litexa persistent store to use Alexa's session attributes instead. Modify your Litexa config file to indicate you'd like this behavior.
{
"name": "Project Name",
"useSessionAttributesForPersistentStore": true,
"deployments": {}
}
You can also override this behavior per-deployment, opting perhaps to only disable permanent storage for test deployments.
{
"name": "Project Name",
"deployments": {
"testing": {
"useSessionAttributesForPersistentStore": true,
}
}
}
Please note that this option modifies the scope of @variables such that they will still store data in between interaction turns, but only until the skill quits. The next time the skill launches, all @data will be lost.
It is also important to note that switching to sessionAttributes limits the size of your persistent storage in accordance with the limitations of sessionAttributes, namely that your total response size, that is to say all your persistent variables, plus any speech, reprompts, directives, and such, cannot exceed 24kb at any given turn. See the ASK documentation on Response Format (opens new window) for more information
# Extra Note: Including production
in the Deployment Target Name
There is a special condition on deployment target names. If the name does not
have the word production
in it, a (<target>)
will be automatically
appended to the name of your skill, with <target>
being the name of the
deployment target you used to deploy the skill. We recommend labeling only
your production skill deployment target(s) with production
.
TIP
We recommend changing the DynamoDB settings for your live skill to ensure that it does not throttle your skill's persistent storage read and writes, which would have an impact of added latency for your customers. Increasing the provisioned capacity units, enabling Auto Scaling, or switching the table to On-Demand capacity are all ways you can make your skill's experience more robust.
See DynamoDB Capacity Modes (opens new window) for more information.
# Adding New Filetypes to the Assets Upload
Litexa filters the kinds of files it will deploy from your assets directory, rather than uploading them all. You can add to this filter by specifying additional file extensions in your Litexa configuration file. Just specify the extension in an array, each beginning with the period. You can specify this key on both the root configuration object, as well as add more in each specific deployment.
{
"name": "my project name",
"deployments": {
"development": {
"additionalAssetExtensions": [".test"]
}
},
"additionalAssetExtensions": [".csv", ".data"]
}
# Additional Resources
- AWS permissions for setting up your IAM user with the required permissions.
- Default AWS Settings for details on the configurations
@litexa/deploy-aws
sets up your AWS resources with.