Page updated Jan 16, 2024

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 development
  • appId: the Amplify Service project Id (optional, see below)
  • envName: the name of your first environment
  • defaultEditor: 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 the appId inside the --amplify parameter, or explicitly as amplify 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 the amplify-frontend- prefix).
  • framework: the frontend framework used in the project, such as react. Only the javascript 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:

  1. config for javascript
    • SourceDir: The project's source directory. The CLI will place and update the aws-exports.js file in it, the aws-exports.js file is used to configure the Amplify 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 the amplify 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 the amplify 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 the amplify run command.
  2. config for android
    • ResDir: The Android project's resource directory, such as app/src/main/res.
  3. config for ios
    • The ios frontend handler does NOT take the config object.

--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 either project or general. Unless explicitly set to general, the project 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 level
  • useProfile: 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 if useProfile is set to true.
  • accessKeyId: The aws access key id if useProfile is set to false.
  • secretAccessKey: The aws secret access key if useProfile is set to false.
  • region: The aws region if useProfile 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 the auth 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:

1AUTHCONFIG="{\
2\"userPoolId\": \"myproject-userpool-id\",\
3\"webClientId\": \"appid-web\",\
4\"nativeClientId\": \"appid-native\",\
5\"identityPoolId\": \"myproject-idp-poolid\"\
6}"
7
8CATEGORIES="{\
9\"auth\":$AUTHCONFIG\
10}"

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.
1STORAGECONFIG="{\
2 \"region\": \"us-east-1\",\
3 \"bucketName\": \"my-project-bucket\"\
4}"
5
6CATEGORIES="{\
7 \"storage\":$STORAGECONFIG\
8}"

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.
1STORAGECONFIG="{\
2 \"region\": \"us-east-1\",
3 \"tables\": {\"
4 \"posts\": \"myproject-posts-dev\",\
5 \"comments\": \"myproject-comments-dev\",\
6 }"\
7}"
8
9CATEGORIES="{\
10 \"storage\":$STORAGECONFIG
11}"

--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
  • 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

1const shell = require('shelljs');
2const amplify = require('./amplify-headless-init-payload.json');
3const cmd =
4 'amplify init --amplify "' +
5 JSON.stringify(amplify.amplify).replaceAll('"', '\\"') +
6 '" --frontend "' +
7 JSON.stringify(amplify.frontend).replaceAll('"', '\\"') +
8 '" --providers "' +
9 JSON.stringify(amplify.providers).replaceAll('"', '\\"') +
10 '" --yes';
11
12if (shell.exec(cmd).code !== 0) {
13 shell.echo('Error amplify init');
14 shell.exit(1);
15}

amplify-headless-init-payload.json content

1{
2 "amplify": {
3 "projectName": "headlessProjectName",
4 "envName": "myenvname",
5 "defaultEditor": "code"
6 },
7 "frontend": {
8 "frontend": "javascript",
9 "framework": "react",
10 "config": {
11 "SourceDir": "src",
12 "DistributionDir": "build",
13 "BuildCommand": "npm run-script build",
14 "StartCommand": "npm run-script start"
15 }
16 },
17 "providers": {
18 "awscloudformation": {
19 "configLevel": "project",
20 "useProfile": false,
21 "profileName": "default"
22 }
23 }
24}

Sample bash script for Unix platform

1#!/bin/bash
2set -e
3IFS='|'
4
5REACTCONFIG="{\
6\"SourceDir\":\"src\",\
7\"DistributionDir\":\"build\",\
8\"BuildCommand\":\"npm run-script build\",\
9\"StartCommand\":\"npm run-script start\"\
10}"
11AWSCLOUDFORMATIONCONFIG="{\
12\"configLevel\":\"project\",\
13\"useProfile\":false,\
14\"profileName\":\"default\",\
15\"accessKeyId\":\"headlessaccesskeyid\",\
16\"secretAccessKey\":\"headlesssecrectaccesskey\",\
17\"region\":\"us-east-1\"\
18}"
19AMPLIFY="{\
20\"projectName\":\"headlessProjectName\",\
21\"envName\":\"myenvname\",\
22\"defaultEditor\":\"code\"\
23}"
24FRONTEND="{\
25\"frontend\":\"javascript\",\
26\"framework\":\"react\",\
27\"config\":$REACTCONFIG\
28}"
29PROVIDERS="{\
30\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\
31}"
32
33amplify init \
34--amplify $AMPLIFY \
35--frontend $FRONTEND \
36--providers $PROVIDERS \
37--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

1#!/bin/bash
2set -e
3IFS='|'
4
5REACTCONFIG="{\
6\"SourceDir\":\"src\",\
7\"DistributionDir\":\"build\",\
8\"BuildCommand\":\"npm run-script build\",\
9\"StartCommand\":\"npm run-script start\"\
10}"
11AWSCLOUDFORMATIONCONFIG="{\
12\"configLevel\":\"project\",\
13\"useProfile\":false,\
14\"profileName\":\"default\",\
15\"accessKeyId\":\"headlessaccesskeyid\",\
16\"secretAccessKey\":\"headlesssecrectaccesskey\",\
17\"region\":\"us-east-1\"\
18}"
19AMPLIFY="{\
20\"projectName\":\"headlessProjectName\",\
21\"defaultEditor\":\"code\"\
22}"
23FRONTEND="{\
24\"frontend\":\"javascript\",\
25\"framework\":\"react\",\
26\"config\":$REACTCONFIG\
27}"
28PROVIDERS="{\
29\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\
30}"
31
32amplify configure project \
33--amplify $AMPLIFY \
34--frontend $FRONTEND \
35--providers $PROVIDERS \
36--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 as javascript.
  • 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

1#!/bin/bash
2set -e
3IFS='|'
4
5CODEGEN="{\
6\"generateCode\":true,\
7\"codeLanguage\":\"javascript\",\
8\"fileNamePattern\":\"src/graphql/**/*.js\",\
9\"generatedFileName\":\"API\",\
10\"generateDocs\":true\
11}"
12
13amplify push \
14--codegen $CODEGEN \
15--yes

amplify pull parameters

The amplify pull command pulls down the latest backend environment to your local development. It is used in two scenarios:

  1. 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.
  2. 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 by appId and envName in the amplify 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 development
  • appId: the Amplify Service project Id
  • envName: the name of the backend environment in the above mention Amplify Service that you want to pull down
  • defaultEditor: 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 the amplify-frontend- prefix).
  • framework: the frontend framework used in the project, such as react. Only the javascript 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:

  1. config for javascript
    • SourceDir: The project's source directory. The CLI will place and update the aws-exports.js file in it, the aws-exports.js file is used to configure the Amplify 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 the amplify 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 the amplify 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 the amplify run command.
  2. config for android
    • ResDir: The Android project's resource directory, such as app/src/main/res.
  3. config for ios
    • The ios frontend handler does NOT take the config object.

--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 either project or general. Unless explicitly set to general, the project 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 level
  • useProfile: 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 if useProfile is set to true.
  • accessKeyId: The aws access key id if useProfile is set to false.
  • secretAccessKey: The aws secret access key if useProfile is set to false.
  • region: The aws region if useProfile is set to false.

Sample script

1#!/bin/bash
2set -e
3IFS='|'
4
5REACTCONFIG="{\
6\"SourceDir\":\"src\",\
7\"DistributionDir\":\"build\",\
8\"BuildCommand\":\"npm run-script build\",\
9\"StartCommand\":\"npm run-script start\"\
10}"
11AWSCLOUDFORMATIONCONFIG="{\
12\"configLevel\":\"project\",\
13\"useProfile\":false,\
14\"profileName\":\"default\",\
15\"accessKeyId\":\"headlessaccesskeyid\",\
16\"secretAccessKey\":\"headlesssecrectaccesskey\",\
17\"region\":\"us-east-1\"\
18}"
19AMPLIFY="{\
20\"projectName\":\"headlessProjectName\",\
21\"appId\":\"amplifyServiceProjectAppId\",\
22\"envName\":\"myenvname\",\
23\"defaultEditor\":\"code\"\
24}"
25FRONTEND="{\
26\"frontend\":\"javascript\",\
27\"framework\":\"react\",\
28\"config\":$REACTCONFIG\
29}"
30PROVIDERS="{\
31\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\
32}"
33
34amplify pull \
35--amplify $AMPLIFY \
36--frontend $FRONTEND \
37--providers $PROVIDERS \
38--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

1#!/bin/bash
2set -e
3
4amplify 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:

1cat 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:

1const amplify_api = require('./myAddApiRequest.json');
2const fs = require('fs');
3const path = require('path');
4
5const schema = fs.readFileSync(
6 path.resolve(__dirname, './schema.graphql'),
7 'utf8'
8);
9
10import('execa').then((module) => {
11 amplify_api.serviceConfiguration.transformSchema = schema;
12 module
13 .execa('amplify', ['add', 'api', '--headless'], {
14 input: JSON.stringify(amplify_api)
15 })
16 .stdout.pipe(process.stdout);
17});

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:

(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:

1"json.schemas": [
2 {
3 "fileMatch": [
4 "*.addauth.json"
5 ],
6 "url": "./node_modules/amplify-headless-interface/schemas/auth/2/AddAuthRequest.schema.json"
7 },
8 {
9 "fileMatch": [
10 "*.updateauth.json"
11 ],
12 "url": "./node_modules/amplify-headless-interface/schemas/auth/2/UpdateAuthRequest.schema.json"
13 },
14 {
15 "fileMatch": [
16 "*.importauth.json"
17 ],
18 "url": "./node_modules/amplify-headless-interface/schemas/auth/1/ImportAuthRequest.schema.json"
19 },
20 {
21 "fileMatch": [
22 "*.addapi.json"
23 ],
24 "url": "./node_modules/amplify-headless-interface/schemas/api/1/AddApiRequest.schema.json"
25 },
26 {
27 "fileMatch": [
28 "*.updateapi.json"
29 ],
30 "url": "./node_modules/amplify-headless-interface/schemas/api/1/UpdateApiRequest.schema.json"
31 }
32]

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:

1{
2 "version": 1,
3 "serviceConfiguration": {
4 "serviceName": "AppSync",
5 "apiName": "myNewHeadlessApi",
6 "transformSchema": "type Todo @model {\r\n id: ID!\r\n name: String!\r\n description: String\r\n}",
7 "defaultAuthType": {
8 "mode": "API_KEY"
9 }
10 }
11}

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:

1{
2 "version": 1,
3 "userPoolId": "myUserPoolId",
4 "webClientId": "myWebAppClientId",
5 "nativeClientId": "myNativeAppClientId",
6 "identityPoolId": "myIdentityPoolId" //optional
7}

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.