見出し画像

Amplify Hostingのビルドが成功しない

α版のリリースにあたってホスト環境へのデプロイを試そうとしたところ、なかなかビルドが成功しませんでした…。夏ごろにハッカソン用にビルド/デプロイしたときはうまくいったのに…何故だ…。

徹夜でトライ&エラーしながらビルドを回すこと十数回…。やっとビルドに成功しました!
申し訳ないことに正確なエラーログなど記録してなかったので正確な現象が説明できませんが、ビルド時に以下の様なエラーが出てバックエンドがpullできずにビルドが失敗していました。

amplify hosting build failed to pull the backend.

Amplifyのバグなのかなぁと思うので直ぐに状況変わりそうですが、一応記事にしてみます。
Amplify CLIのバージョンは12.8.2です。

デフォルトでビルドコマンドに書かれているamplifyPushというコマンドの時点でエラーになっていたのでこの辺りを調べてみることに。

大体このamplifyPushコマンドは何をしているのだ、と探してみるとGithubにありました。

https://github.com/aws-amplify/amplify-hosting/blob/main/scripts/amplifyPush.sh

ただし、「This script has been deprecated. Please refer to https://docs.amplify.aws/cli/usage/headless/ to run headless scripts in your build system.」
とのこと…。

「ビルド設定の構成」ドキュメントと違うじゃん…。と戸惑いながら古いコミットを辿り、deprecatedになる前のシェルスクリプトを参考にしながら自前のamplifyPushコマンドをリポジトリルートに作ってそちらを実行することに。
とりあえずビルドが成功することだけを目指したので不要なコードがたくさん入っていますが、結局以下の記述でビルドが成功しました。
FRONTENDの引数を追加することでamplify pullが成功しました。

#!/usr/bin/env bash
set -e
IFS='|'

help_output () {
    echo "usage: amplify-push <--environment|-e <name>> <--simple|-s>"
    echo "  --environment  The name of the Amplify environment to use"
    echo "  --simple  Optional simple flag auto-includes stack info from env cache"
    exit 1
}

init_env () {
    ENV=$1
    AMPLIFY=$2
    PROVIDERS=$3
    CODEGEN=$4
    AWSCONFIG=$5
    CATEGORIES=$6
    FRONTEND=$7

    echo "# Start initializing Amplify environment: ${ENV}"
    if [[ -z ${STACKINFO} ]];
    then
        echo "# Initializing new Amplify environment: ${ENV} (amplify init)"
        [[ -z ${CATEGORIES} ]] && amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --frontend ${FRONTEND} --yes || amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --categories ${CATEGORIES} --frontend ${FRONTEND} --yes
        echo "# Environment ${ENV} details:"
        amplify env get --name ${ENV}
    else
        echo "STACKINFO="${STACKINFO}
        echo "# Importing Amplify environment: ${ENV} (amplify env import)"
        amplify env import --name ${ENV} --config "${STACKINFO}" --awsInfo ${AWSCONFIG} --yes;
        echo "# Initializing existing Amplify environment: ${ENV} (amplify init)"
        [[ -z ${CATEGORIES} ]] && amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --frontend ${FRONTEND} --yes || amplify init --amplify ${AMPLIFY} --providers ${PROVIDERS} --codegen ${CODEGEN} --categories ${CATEGORIES} --frontend ${FRONTEND} --yes
        echo "# Environment ${ENV} details:"
        amplify env get --name ${ENV}
    fi
    echo "# Done initializing Amplify environment: ${ENV}"
}

ENV=""
IS_SIMPLE=false
POSITIONAL=()
while [[ $# -gt 0 ]]
    do
    key="$1"
    case ${key} in
        -e|--environment)
        ENV=$2
        shift
        ;;
        -r|--region)
        REGION=$2
        shift
        ;;
        -s|--simple)
        IS_SIMPLE=true
        shift
        ;;
        *)
        POSITIONAL+=("$1")
        shift
        ;;
    esac
done
set -- "${POSITIONAL[@]}"

# if no provided environment name, use default env variable, then user override
if [[ ${ENV} = "" ]];
then
    ENV=${AWS_BRANCH}
fi

if [[ ${USER_BRANCH} != "" ]];
then
    ENV=${USER_BRANCH}
fi

# strip slashes, limit to 10 chars
ENV=$(echo ${ENV} | sed 's;\\;;g' | sed 's;\/;;g' | cut -c -10)

# Check valid environment name
if [[ -z ${ENV} || "${ENV}" =~ [^a-zA-Z0-9\-]+ ]] ; then help_output ; fi

AWSCONFIG="{\
\"configLevel\":\"project\",\
\"useProfile\":true,\
\"profileName\":\"default\",\
\"AmplifyAppId\":\"${AWS_APP_ID}\"\
}"
AMPLIFY="{\
\"envName\":\"${ENV}\",\
\"appId\":\"${AWS_APP_ID}\"\
}"
PROVIDERS="{\
\"awscloudformation\":${AWSCONFIG}\
}"
CODEGEN="{\
\"generateCode\":false,\
\"generateDocs\":false\
}"
CATEGORIES=""
if [[ -z ${AMPLIFY_FACEBOOK_CLIENT_ID} && -z ${AMPLIFY_GOOGLE_CLIENT_ID} && -z ${AMPLIFY_AMAZON_CLIENT_ID} ]]; then
    CATEGORIES=""
else
    AUTHCONFIG="{\
    \"facebookAppIdUserPool\":\"${AMPLIFY_FACEBOOK_CLIENT_ID}\",\
    \"facebookAppSecretUserPool\":\"${AMPLIFY_FACEBOOK_CLIENT_SECRET}\",\
    \"googleAppIdUserPool\":\"${AMPLIFY_GOOGLE_CLIENT_ID}\",\
    \"googleAppSecretUserPool\":\"${AMPLIFY_GOOGLE_CLIENT_SECRET}\",\
    \"amazonAppIdUserPool\":\"${AMPLIFY_AMAZON_CLIENT_ID}\",\
    \"amazonAppSecretUserPool\":\"${AMPLIFY_AMAZON_CLIENT_SECRET}\"\
    }"
    CATEGORIES="{\
    \"auth\":$AUTHCONFIG\
    }"
fi

FRONTEND="{\
\"frontend\":\"javascript\",\
\"framework\":\"vue\",\
\"config\": {\
\"SourceDir\": \"src\",\
\"DistributionDir\": \"dist\",\
\"BuildCommand\": \"npm run build\",\
\"StartCommand\": \"npm run preview\"\
}"

# Handle old or new config file based on simple flag
if [[ ${IS_SIMPLE} ]];
then
    echo "# Getting Amplify CLI Cloud-Formation stack info from environment cache"
    export STACKINFO="$(envCache --get stackInfo)"
    init_env ${ENV} ${AMPLIFY} ${PROVIDERS} ${CODEGEN} ${AWSCONFIG} ${CATEGORIES} ${FRONTEND}
    echo "# Store Amplify CLI Cloud-Formation stack info in environment cache"
    STACKINFO="$(amplify env get --json --name ${ENV})"
    envCache --set stackInfo ${STACKINFO}
    echo "STACKINFO="${STACKINFO}
else
    # old config file, above steps performed outside of this script
    init_env ${ENV} ${AMPLIFY} ${PROVIDERS} ${CODEGEN} ${AWSCONFIG} ${CATEGORIES} ${FRONTEND}
fi

上記のシェルスクリプトを以下のビルド設定で実行します。(preBuild要らないかも。)

version: 1
backend:
  phases:
    preBuild:
      commands:
        - echo 'preBuild phase.'
    build:
      commands:
        - echo 'build phase.'
        - ./amplifyPush.sh --simple
frontend:
  phases:
    preBuild:
      commands:
        - npm install
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

リファクタが必要な雑コードですがとりあえずビルド成功時点の記録として残してみました。
では今回はここまで。

もしこの記事があなたのお役に立てたなら幸いです。 よろしければサポートをお願いします。今後の制作資金にさせていただきます!