AWSJavaScriptNode.jsTypeScript

AWS AmplifyをNode.js / TypeScriptから操作する

AWS Amplifyを触ってみた系の記事はそこそこ出てきているので、あえてせっかく用意されたコンソールを使わずにやってみましょう。 AWS re:invent 2018 Advent Calendar 2018の19日 […]

広告ここから
広告ここまで

AWS Amplifyを触ってみた系の記事はそこそこ出てきているので、あえてせっかく用意されたコンソールを使わずにやってみましょう。

AWS re:invent 2018 Advent Calendar 2018の19日分です。

前提条件

すでにAWS Amplifyコンソールからアプリを作成済みであるとします。また、リポジトリにはCodeCommitを使用しています。

CodeCommitをリポジトリにできるのですが、createAppメソッドがOAuthトークン必須なのでめんどくさかった・・・

だれかCode CommitをソースにしてcreateAppメソッド実行した記事お願いします。

作成済みアプリのデータを取得する

何はともあれ作成済みアプリのデータを取るところから始めましょう。

import {Amplify} from 'aws-sdk';

const amplify = new Amplify()

export const getMyApplication = async (): Promise<Amplify.Types.GetAppResult> => {
    const data = await amplify.getApp({
        appId: 'YOUR_APP_ID'
    }).promise()
    console.log(data)
    return data
}

レスポンスがこんな感じです。公開サイトのスクショURLやビルド設定などもアプリケーションの情報として持っている様子ですね。


{ app: 
   { appId: 'YOUR_APP_ID',
     appArn: 'arn:aws:amplify:us-east-1:999999:apps/YOUR_APP_ID',
     name: 'my-first-react',
     tags: {},
     description: null,
     repository: 'YOUR_REPO',
     platform: 'WEB',
     createTime: 2018-12-13T10:56:57.246Z,
     updateTime: 2018-12-13T11:06:34.750Z,
     iamServiceRoleArn: 'arn:aws:iam::99999:role/service-role/AWSAmplifyExecutionRole-YOUR_APP_ID',
     environmentVariables: {},
     defaultDomain: 'YOUR_APP_ID.amplifyapp.com',
     enableBranchAutoBuild: false,
     enableBasicAuth: false,
     basicAuthCredentials: null,
     customRules: [ [Object], [Object], [Object] ],
     productionBranch: 
      { lastDeployTime: 2018-12-13T11:00:04.211Z,
        status: 'SUCCEED',
        thumbnailUrl: 'https://aws-amplify-prod-us-east-1-artifacts.s3.amazonaws.com/YOUR_APP_ID/master/SCREENSHOTS/thumbnail.png?X-Amz-Security-Token=XXXXXXX',
        branchName: 'master' },
     buildSpec: 'version: 0.1\nfrontend:\n  phases:\n    preBuild:\n      commands:\n        - yarn install\n    build:\n      commands:\n        - yarn run build\n  artifacts:\n    baseDirectory: build\n    files:\n      - \'**/*\'\n  cache:\n    paths:\n      - node_modules/**/*\n' } }

customeRulesには、リダイレクトルールが設定されています。

[ { source: 'www.example.com',
    target: 'https://example.com',
    status: '301',
    condition: null },
  { source: '/<*>',
    target: '/index.html',
    status: '404',
    condition: null } ]

SPAでルーター組んだ時に必要なindex.htmlへのリダイレクトもデフォルトでついていますね。これ、逆に考えるとSSGで作ったサイトをデプロイするときは要注意かもです。

手動でアプリをリリースする

startJobで任意のタイミングでアプリのリリースを行うことができます。

import {Amplify} from 'aws-sdk';
const amplify = new Amplify()

const branchName: string = 'master'
const appId: string = 'YOUR_APP_ID'

export const startNewRelease = async (): Promise<Amplify.Types.ListJobsResult> => {
    await amplify.startJob({
        appId,
        branchName,
        jobType: 'RELEASE'
    }).promise()
    const data = await amplify.listJobs({
        appId,
        branchName
    }).promise()
    return data
}

実行すると新しいジョブが追加されています。

{ jobSummaries: 
   [ { jobArn: 'arn:aws:amplify:us-east-1:999999:apps/YOUR_APP_ID/branches/master/jobs/0000000002',
       jobId: '2',
       commitId: 'HEAD',
       commitMessage: null,
       commitTime: 2018-12-19T02:52:14.606Z,
       startTime: 2018-12-19T02:52:14.984Z,
       status: 'RUNNING',
       endTime: null,
       jobType: null },
...

jobIdを使うことで、retryも可能です。

import {Amplify} from 'aws-sdk';
const amplify = new Amplify()

const branchName: string = 'master'
const appId: string = 'YOUR_APP_ID'

export const startNewRelease = async (): Promise<Amplify.Types.ListJobsResult> => {
    await amplify.startJob({
        appId,
        branchName,
        jobType: 'RETRY',
        jobId: '2',
    }).promise()
    const data = await amplify.listJobs({
        appId,
        branchName
    }).promise()
    return data
}

また、すでにそのブランチでjobが進行中の場合、エラーが発生します。

{ 
  message: 'The requested branch arn:aws:amplify:us-east-1:99999:apps/YOUR_APP_ID/branches/master already have pending or running jobs',
  code: 'LimitExceededException',
  time: 2018-12-19T02:54:28.440Z,
  requestId: '668c23d6-0339-11e9-9cf4-39a99096c993',
  statusCode: 429,
  retryable: false,
  retryDelay: 41.97412555483295 }

GatsbyにWP API連携させて動的にコンテンツを取得したい場合など、定期的にビルドジョブを走らせたい時が稀によくあります。そういうときはこのstartJobをCloudWatch Event -> Lambdaで実行してやるとよいでしょう。

アプリの設定を更新する

ビルドやリダイレクトなどの設定はだいたい、アプリについています。なのでupdateAppでだいたい更新可能です。

import {Amplify} from 'aws-sdk';
const amplify = new Amplify()

const appId: string = 'YOUR_APP_ID'

export const updateApplication = async (): Promise<Amplify.Types.UpdateAppResult> => {
    const { app } = await amplify.getApp({
        appId
    }).promise()
    const {
        basicAuthCredentials,
        buildSpec,
        customRules,
        enableBasicAuth,
        enableBranchAutoBuild,
        environmentVariables,
        iamServiceRoleArn,
        name,
        platform
    } = app
    const param = {
        appId,
        basicAuthCredentials,
        buildSpec,
        customRules,
        description: 'This is example app to update from aws-sdk',
        enableBasicAuth,
        enableBranchAutoBuild,
        environmentVariables,
        iamServiceRoleArn,
        name,
        platform
    }
    const data = await amplify.updateApp(param).promise()
    return data
}

getAppの戻り値をそのまま突っ込むとUnexpected key ~で怒られるので、横着はやめましょう。

応用:サイト全体にBASIC認証をかける

basicAuthCredentialsenableBasicAuthでBASIC認証をかけれます。

credentialsの方はBASE64でエンコードした値を入れるのがポイントです。

import {Amplify} from 'aws-sdk';

const amplify = new Amplify()
const appId: string = 'YOUR_APP_ID'

const generateCredentials = (username: string, password: string): string => {
    return Buffer.from(`${username}:${password}`).toString('base64')
}

export const setBasicAuth = async (): Promise<Amplify.Types.UpdateAppResult> => {
    const { app } = await amplify.getApp({
        appId
    }).promise()
    const {
        buildSpec,
        customRules,
        description,
        enableBranchAutoBuild,
        environmentVariables,
        iamServiceRoleArn,
        name,
        platform
    } = app
    const basicAuthCredentials = generateCredentials('admin', 'adminadmin')
    const param = {
        appId,
        basicAuthCredentials,
        buildSpec,
        customRules,
        description,
        enableBasicAuth: true,
        enableBranchAutoBuild,
        environmentVariables,
        iamServiceRoleArn,
        name,
        platform
    }
    const data = await amplify.updateApp(param).promise()
    return data
}

解除はbasicAuthCredentials=''かつenableBasicAuth=falseにしてやればOKです。

ブランチ単位で設定を変える

BASIC認証など、一部はブランチ単位で設定を変えれます。

import {Amplify} from 'aws-sdk';

const amplify = new Amplify()

const branchName: string = 'master'
const appId: string = 'YOUR_APP_ID'

const generateCredentials = (username: string, password: string): string => {
    return Buffer.from(`${username}:${password}`).toString('base64')
}

export const setBranchBasicAuth = async (): Promise<Amplify.Types.UpdateBranchResult> => {
    const { branch } = await amplify.getBranch({
        appId,
        branchName
    }).promise()
    const {
        buildSpec,
        description,
        enableAutoBuild,
        enableNotification,
        environmentVariables,
        framework,
        stage,
        ttl
    } = branch

    const data = await amplify.updateBranch({
        appId,
        buildSpec,
        description,
        enableAutoBuild,
        enableNotification,
        environmentVariables,
        framework,
        stage,
        ttl,
        basicAuthCredentials: generateCredentials('admin', 'adminadmin'),
        enableBasicAuth: true,
        branchName
    }).promise()
    return data
}

やっていることは同じですね。こちらも更新したい値だけいじってそのまま突っ込むとエラーになる様子なので、要注意です。

おわりに

AWS Amplifyですが、アプリを作るところでOAuth token必須になっていること以外はすごくAPI / SDKからも扱いやすいです。

他にもいろいろなAPIがありますので、ぜひ触ってみてください。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts