Headless mode for CI/CD
Several commands in the Amplify CLI support arguments which could be used in a CI/CD workflow or other non-interactive shell. The CLI will work non-interactively if the required information is provided by an argument.
Arguments are used mostly for scripting so that the command execution flow is not interrupted by prompts. Examples for this can be found here
--yes
flag
The --yes
flag, or its alias -y
, suppresses command line prompts if defaults are available, and uses the defaults in command execution. The following commands take the --yes
flag:
amplify init
amplify configure project
amplify push
amplify publish
amplify pull
amplify init
parameters
The amplify init
command takes these parameters:
--amplify
--frontend
--providers
--categories
--yes
--app
--amplify
Contains basic information of the project, it has these keys:
projectName
: the name of the project under developmentappId
: the Amplify Service project Id (optional, see below)envName
: the name of your first environmentdefaultEditor
: your default code editor
The appId
parameter is optional and it is used in two use cases.
- Amplify Service uses it internally when you initialize a project on Amplify web console.
- For project migrations. For projects initialized by Amplify CLI version prior to 4.0.0, no Amplify Service project is created online to track the backend environment's resources. The latest version of the Amplify CLI will create a new Amplify Service project for them in the post-push check. If you wanted to add the backend environment to an existing Amplify Service project instead of creating a new one, you can run
amplify init
again, and provide theappId
inside the--amplify
parameter, or explicitly asamplify init --appId <Amplify-Service-Project-AppId>
.
--frontend
Contains information for the CLI's frontend plugin, it has these keys:
frontend
: the name of the chosen frontend plugin (without theamplify-frontend-
prefix).framework
: the frontend framework used in the project, such asreact
. Only thejavascript
frontend handler takes it.config
: the configuration settings for the frontend plugin.
There are currently three official frontend plugins, and the following are the specifications of their respective config
object:
config
forjavascript
SourceDir
: The project's source directory. The CLI will place and update theaws-exports.js
file in it, theaws-exports.js
file is used to configure theAmplify JS
library.DistributionDir
: The project's distribution directory, where the build artifacts are stored. The CLI will upload the contents inside this directory to the S3 hosting buckets in the execution of theamplify publish
command.BuildCommand
: The build command for the project. The CLI invokes the build command before uploading the contents in the distribution directory in the execution of theamplify publish
command.StartCommand
: The start command for the project, used for local testing. The CLI invokes the start command after it has pushed the latest development of the backend to the cloud in the execution of theamplify run
command.
config
forandroid
ResDir
: The Android project's resource directory, such asapp/src/main/res
.
config
forios
- The
ios
frontend handler does NOT take theconfig
object.
- The
--providers
Contains configuration settings for provider plugins. The key is the name of the provider plugin (without the amplify-provider-
prefix), and the value is its configuration. Provider plugins contained in this object will be initialized, and able to provide functionalities for creation and maintenance of the cloud resources.
Currently there is only one official provider plugin: amplify-provider-awscloudformation
, its configuration is for the CLI to resolve aws credentials and region, the following are the specifications:
configLevel
: The configuration level is eitherproject
orgeneral
. Unless explicitly set togeneral
, theproject
level is chosen.general
level means the CLI will not manage configuration at the project level, it instead relies on the AWS SDK to resolve aws credentials and region. To learn how it works, check the AWS SDK's documents on credentials and region.project
level means the configuration is managed at the project level by the CLI, each project gets its own independent configuration. The following attributes are used only when the configuration is at project leveluseProfile
: A boolean indicating whether to use a profile defined in the shared config file (~/.aws/config
) and credentials file (~/.aws/credentials
).profileName
: The name of the profile ifuseProfile
is set to true.accessKeyId
: The aws access key id ifuseProfile
is set to false.secretAccessKey
: The aws secret access key ifuseProfile
is set to false.region
: The aws region ifuseProfile
is set to false.
--categories
Contains configuration settings for resources in the given categories. The key is the name of the category and the value is its configuration. There are resource parameters that are not persisted into configuration files and requires prompting for them during a headless CLI operation and to support headless workflows they are required to be passed in for each resource..
Imported resources
Currently auth
and storage
category resources can be imported to an Amplify CLI project.
auth
category
userPoolId
: The Id of the Cognito User Pool that was imported into the project.webClientId
: The Id of the app client configured for the given Cognito User Pool to be used by web applications.nativeClientId
: The Id of the app client configured for the given Cognito User Pool to be used by Native applications.identityPoolId
: In case if an Cognito Identity Pool was also configured for theauth
resource this parameter is the Id of that resource. If there is no associated Cognito Identity Pool was configured, this parameter should not be passed in.
Sample auth
category configuration:
AUTHCONFIG="{\\"userPoolId\": \"myproject-userpool-id\",\\"webClientId\": \"appid-web\",\\"nativeClientId\": \"appid-native\",\\"identityPoolId\": \"myproject-idp-poolid\"\}"
CATEGORIES="{\\"auth\":$AUTHCONFIG\}"
storage
category
Storage category supports the importing of S3 Buckets and DynamoDB tables. They require different parameter sets within the storage category.
S3 Buckets
region
: The region of the S3 bucket resource. S3 Buckets are global, but the CLI requires to storage of the region as a parameter, so it needs to be passed in. Currently it must be the same region where the Amplify project was created.bucketName
: The name of the imported S3 bucket.
STORAGECONFIG="{\ \"region\": \"us-east-1\",\ \"bucketName\": \"my-project-bucket\"\}"
CATEGORIES="{\ \"storage\":$STORAGECONFIG\}"
DynamoDB Tables
An Amplify project can have multiple DynamoDB storage resources imported and the parameters must be supplied to each of them.
region
: The region of the DynamoDB table resources. Currently it must be the same region where the Amplify project was created.tables
: An object where the key is the Amplify resource name and the value is the name of the DynamoDB table.
STORAGECONFIG="{\ \"region\": \"us-east-1\", \"tables\": {\" \"posts\": \"myproject-posts-dev\",\ \"comments\": \"myproject-comments-dev\",\ }"\}"
CATEGORIES="{\ \"storage\":$STORAGECONFIG}"
--app
amplify init --app git@github.com:<github-username>/<repository-name>.git
Installs, initializes, and provisions resources for a sample amplify project from the provided GitHub repository URL. This option must be executed in an empty directory. The sample repository must have an amplify folder, including the following:
-
project-config.json
in .config folder -
backend-config.json
in backend folder -
The necessary cloudformation files in the backend folder
- e.g. stacks,
schema.graphql
for api - e.g. cloudformation template for auth
- e.g. stacks,
-
local files local-env.json and local-aws-info.json are NOT required
If the repository contains a yarn.lock
and/or package.json
file, the sample will be installed with the corresponding package manager and started after resources have been provisioned.
Sample script
const shell = require('shelljs');const amplify = require('./amplify-headless-init-payload.json');const cmd = 'amplify init --amplify "' + JSON.stringify(amplify.amplify).replaceAll('"', '\\"') + '" --frontend "' + JSON.stringify(amplify.frontend).replaceAll('"', '\\"') + '" --providers "' + JSON.stringify(amplify.providers).replaceAll('"', '\\"') + '" --yes';
if (shell.exec(cmd).code !== 0) { shell.echo('Error amplify init'); shell.exit(1);}
amplify-headless-init-payload.json content
{ "amplify": { "projectName": "headlessProjectName", "envName": "myenvname", "defaultEditor": "code" }, "frontend": { "frontend": "javascript", "framework": "react", "config": { "SourceDir": "src", "DistributionDir": "build", "BuildCommand": "npm run-script build", "StartCommand": "npm run-script start" } }, "providers": { "awscloudformation": { "configLevel": "project", "useProfile": false, "profileName": "default" } }}
Sample bash script for Unix platform
#!/bin/bashset -eIFS='|'
REACTCONFIG="{\\"SourceDir\":\"src\",\\"DistributionDir\":\"build\",\\"BuildCommand\":\"npm run-script build\",\\"StartCommand\":\"npm run-script start\"\}"AWSCLOUDFORMATIONCONFIG="{\\"configLevel\":\"project\",\\"useProfile\":false,\\"profileName\":\"default\",\\"accessKeyId\":\"headlessaccesskeyid\",\\"secretAccessKey\":\"headlesssecrectaccesskey\",\\"region\":\"us-east-1\"\}"AMPLIFY="{\\"projectName\":\"headlessProjectName\",\\"envName\":\"myenvname\",\\"defaultEditor\":\"code\"\}"FRONTEND="{\\"frontend\":\"javascript\",\\"framework\":\"react\",\\"config\":$REACTCONFIG\}"PROVIDERS="{\\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\}"
amplify init \--amplify $AMPLIFY \--frontend $FRONTEND \--providers $PROVIDERS \--yes
amplify configure project
parameters
The amplify configure project
command allows the user to change the configuration settings that were first set by amplify init
, and it takes the same parameters as the amplify init
command:
--amplify
--frontend
--providers
--yes
Sample script
#!/bin/bashset -eIFS='|'
REACTCONFIG="{\\"SourceDir\":\"src\",\\"DistributionDir\":\"build\",\\"BuildCommand\":\"npm run-script build\",\\"StartCommand\":\"npm run-script start\"\}"AWSCLOUDFORMATIONCONFIG="{\\"configLevel\":\"project\",\\"useProfile\":false,\\"profileName\":\"default\",\\"accessKeyId\":\"headlessaccesskeyid\",\\"secretAccessKey\":\"headlesssecrectaccesskey\",\\"region\":\"us-east-1\"\}"AMPLIFY="{\\"projectName\":\"headlessProjectName\",\\"defaultEditor\":\"code\"\}"FRONTEND="{\\"frontend\":\"javascript\",\\"framework\":\"react\",\\"config\":$REACTCONFIG\}"PROVIDERS="{\\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\}"
amplify configure project \--amplify $AMPLIFY \--frontend $FRONTEND \--providers $PROVIDERS \--yes
amplify push/publish
parameters
The amplify publish
command internally executes amplify push
so it takes the same parameters as push command. The amplify push
command takes the following parameters
--codegen
--yes
--force
--allow-destructive-graphql-schema-updates
--codegen
Contains configuration for AppSync codegen, the following are the specifications:
generateCode
:
A boolean indicating if to generate code for your GraphQL API.codeLanguage
:
The targeted language of the generated code, such asjavascript
.fileNamePattern
:
The file name pattern of GraphQL queries, mutations and subscriptions.generatedFileName
:
The file name for the generated code.generateDocs
:
A boolean indicating whether to generate GraphQL statements (queries, mutations and subscription) based on the GraphQL schema types. The generated version will overwrite the current GraphQL queries, mutations and subscriptions.
--yes
Will skip all interactive prompts by selecting default options.
--force
Pushes all resources regardless of update status and bypasses all guardrails to push the local state to the cloud. Only use this flag if you have tested the change in a non-production environment and fully understand the implications.
It includes all of the behavior of --allow-destructive-graphql-schema-updates
--allow-destructive-graphql-schema-updates
Pushes schema changes that require removal or replacement of underlying tables. See update schema.
Sample script
#!/bin/bashset -eIFS='|'
CODEGEN="{\\"generateCode\":true,\\"codeLanguage\":\"javascript\",\\"fileNamePattern\":\"src/graphql/**/*.js\",\\"generatedFileName\":\"API\",\\"generateDocs\":true\}"
amplify push \--codegen $CODEGEN \--yes
amplify pull
parameters
The amplify pull
command pulls down the latest backend environment to your local development. It is used in two scenarios:
- On projects already initialized by the Amplify CLI, it pulls down the latest from the Cloud and updates the contents in the
amplify/#current-cloud-backend
directory. The command does not take any parameters when used in this scenario. - On projects NOT yet initialized by the Amplify CLI, it pulls down a particular backend environment, and "attaches" it to the project. It will fully set up the
amplify
directory for the project. The backend environment being pulled is specified byappId
andenvName
in theamplify
parameter (see below). The command takes the following parameters when used in this scenario.
--amplify
--frontend
--providers
--yes
--amplify
Contains basic information of the project, it has these keys:
projectName
: the name of the project under developmentappId
: the Amplify Service project IdenvName
: the name of the backend environment in the above mention Amplify Service that you want to pull downdefaultEditor
: your default code editor
--frontend
Contains information for the CLI's frontend plugin, it has these keys:
frontend
: the name of the chosen frontend plugin (without theamplify-frontend-
prefix).framework
: the frontend framework used in the project, such asreact
. Only thejavascript
frontend handler takes it.config
: the configuration settings for the frontend plugin.
There are currently three official frontend plugins, and the following are the specifications of their respective config
object:
config
forjavascript
SourceDir
: The project's source directory. The CLI will place and update theaws-exports.js
file in it, theaws-exports.js
file is used to configure theAmplify JS
library.DistributionDir
: The project's distribution directory, where the build artifacts are stored. The CLI will upload the contents inside this directory to the S3 hosting buckets in the execution of theamplify publish
command.BuildCommand
: The build command for the project. The CLI invokes the build command before uploading the contents in the distribution directory in the execution of theamplify publish
command.StartCommand
: The start command for the project, used for local testing. The CLI invokes the start command after it has pushed the latest development of the backend to the cloud in the execution of theamplify run
command.
config
forandroid
ResDir
: The Android project's resource directory, such asapp/src/main/res
.
config
forios
- The
ios
frontend handler does NOT take theconfig
object.
- The
--providers
The pull command is tied to the official provider plugin: amplify-provider-awscloudformation
to pull down and attach a backend environment to your frontend project.
configLevel
: The configuration level is eitherproject
orgeneral
. Unless explicitly set togeneral
, theproject
level is chosen.general
level means the CLI will not manage configuration at the project level, it instead relies on the AWS SDK to resolve aws credentials and region. To learn how it works, check the AWS SDK's documents on credentials and region.project
level means the configuration is managed at the project level by the CLI, each project gets its own independent configuration. The following attributes are used only when the configuration is at project leveluseProfile
: A boolean indicating whether to use a profile defined in the shared config file (~/.aws/config
) and credentials file (~/.aws/credentials
).profileName
: The name of the profile ifuseProfile
is set to true.accessKeyId
: The aws access key id ifuseProfile
is set to false.secretAccessKey
: The aws secret access key ifuseProfile
is set to false.region
: The aws region ifuseProfile
is set to false.
Sample script
#!/bin/bashset -eIFS='|'
REACTCONFIG="{\\"SourceDir\":\"src\",\\"DistributionDir\":\"build\",\\"BuildCommand\":\"npm run-script build\",\\"StartCommand\":\"npm run-script start\"\}"AWSCLOUDFORMATIONCONFIG="{\\"configLevel\":\"project\",\\"useProfile\":false,\\"profileName\":\"default\",\\"accessKeyId\":\"headlessaccesskeyid\",\\"secretAccessKey\":\"headlesssecrectaccesskey\",\\"region\":\"us-east-1\"\}"AMPLIFY="{\\"projectName\":\"headlessProjectName\",\\"appId\":\"amplifyServiceProjectAppId\",\\"envName\":\"myenvname\",\\"defaultEditor\":\"code\"\}"FRONTEND="{\\"frontend\":\"javascript\",\\"framework\":\"react\",\\"config\":$REACTCONFIG\}"PROVIDERS="{\\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\}"
amplify pull \--amplify $AMPLIFY \--frontend $FRONTEND \--providers $PROVIDERS \--yes
amplify delete
parameters
The amplify delete
command deletes all of the resources tied to the current project in the cloud, and removes all of the local files created by the Amplify CLI from the filesystem. The amplify delete
command takes these parameters:
--force
--force
Equivalent to the --yes
parameter that other commands support for use in headless environments.
Sample script
#!/bin/bashset -e
amplify delete --force
Headless category payloads
Some categories' headless mode work differently than above in that they expect a JSON payload on stdin
rather than reading command parameters. The --headless
flag is used to let Amplify CLI know that it should read the JSON payload in a single line from stdin
. The input JSON is validated against the expected shape (described below). Once the validation passes, the operation is executed.
Because the CLI reads a single line from
stdin
, it is necessary to make sure the JSON does not contain any newlines. jq can be used to accomplish this:
cat myAddApiRequest.json | jq -c | amplify add api --headless
As an alternative to using jq
, here's an example Node.js script that adds an API:
const amplify_api = require('./myAddApiRequest.json');const fs = require('fs');const path = require('path');
const schema = fs.readFileSync( path.resolve(__dirname, './schema.graphql'), 'utf8');
import('execa').then((module) => { amplify_api.serviceConfiguration.transformSchema = schema; module .execa('amplify', ['add', 'api', '--headless'], { input: JSON.stringify(amplify_api) }) .stdout.pipe(process.stdout);});
Supported commands
The commands that currently support this method of supplying headless parameters are:
amplify add auth --headless
amplify import auth --headless
amplify update auth --headless
amplify add api --headless
amplify update api --headless
amplify add storage --headless
amplify import storage --headless
amplify remove storage --headless
amplify update storage --headless
Payload structure
The structure of the JSON objects supplied on stdin
are defined in amplify-headless-interface. This package contains both JSON Schema and TypeScript definitions for:
- Add Auth Payload
- Import Auth Payload
- Update Auth Payload
- Add API Payload
- Update API Payload
- Add Storage Payload
- Import Storage Payload
- Remove Storage Payload
- Update Storage Payload
(Optional) IDE setup for headless development
To get started, install the interface package using npm i amplify-headless-interface
. Then, if your editor supports it, configure your editor to know about the schemas in this package.
In Visual Studio Code add the following to settings.json
under the json.schemas
block to associate the specified file extensions with the corresponding schemas:
"json.schemas": [ { "fileMatch": [ "*.addauth.json" ], "url": "./node_modules/amplify-headless-interface/schemas/auth/2/AddAuthRequest.schema.json" }, { "fileMatch": [ "*.updateauth.json" ], "url": "./node_modules/amplify-headless-interface/schemas/auth/2/UpdateAuthRequest.schema.json" }, { "fileMatch": [ "*.importauth.json" ], "url": "./node_modules/amplify-headless-interface/schemas/auth/1/ImportAuthRequest.schema.json" }, { "fileMatch": [ "*.addapi.json" ], "url": "./node_modules/amplify-headless-interface/schemas/api/1/AddApiRequest.schema.json" }, { "fileMatch": [ "*.updateapi.json" ], "url": "./node_modules/amplify-headless-interface/schemas/api/1/UpdateApiRequest.schema.json" }]
Create a file such as MyAuthTemplate.addauth.json
. Once you start editing, Visual Studio Code will provide auto-completion and suggestions based on the schema.
If you prefer not to add this configuration, you can also specify a
$schema
block your JSON body to tell Visual Studio Code how to validate the JSON. See Visual Studio Code's JSON schemas and settings for more details on this configuration.
Example: "amplify add api" headless configuration
This example showcases how to use headless mode to configure amplify add api
.
Create a file called newHeadlessApi.addapi.json
and paste in the following contents:
{ "version": 1, "serviceConfiguration": { "serviceName": "AppSync", "apiName": "myNewHeadlessApi", "transformSchema": "type Todo @model {\r\n id: ID!\r\n name: String!\r\n description: String\r\n}", "defaultAuthType": { "mode": "API_KEY" } }}
Run cat newHeadlessApi.addapi.json | jq -c | amplify add api --headless
to add the API resource.
Example: "amplify import auth" headless configuration
This example showcases how to use headless mode to configure amplify import auth
.
Create a file called authconfig.importauth.json
and paste in the following contents:
{ "version": 1, "userPoolId": "myUserPoolId", "webClientId": "myWebAppClientId", "nativeClientId": "myNativeAppClientId", "identityPoolId": "myIdentityPoolId" //optional}
Run cat authconfig.importauth.json | jq -c | amplify import auth --headless
to import an Cognito resource.
If you don't have
jq
installed, see https://stedolan.github.io/jq/download.