Amplify Gen2 を CodeCatalyst と Amazon Q（生成AI）を使って理解していく

# はじめに
AWS Summit Japan 2024 に参加してきました。久しぶりにオンラインではなく現地参加で技術情報を浴びてきましたので手を動かさずにはいられないと思い記事を執筆します。

今年の AWS Summit は生成AI祭りでした。`Amazon Bedrock` の話を中心に、個人的に刺さったキーワードが `CodeCatalyst`, `Amazon Q`, `Amplify Gen2` です。

それでは、実際に手を動かしながら理解していきたいと思います。
CodeCatalyst で開発環境を作り、Amazon Q に開発支援をしてもらいながら、Amplify Gen2 でフロントは React アプリケーション、バックエンドは DynamoDB という構成にしたいと思います。

おそらく後日アーカイブ動画が出ると思いますが、本記事を書くきっかけになったセッションは以下の２つです。

- AWS Amplify と Amazon Q Developer を活用した生成 AI アプリケーションの作り方
- Amazon CodeCatalyst と Amazon Q で開発者の生産性を向上！ - AI アシスタントの活用方法 -

# CodeCatalyst とは、使い始める

CodeCatalyst の概要は以下の公式ページをご覧ください。開始するを押してセットアップしていきます。ここから先のキャプチャーは Amazon CodeCatalyst 及び AWS 上の画面キャプチャを引用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/07cf2afb-b15d-3060-96ed-be8951ead64d.png)

（出典）https://aws.amazon.com/jp/codecatalyst/

`Sign in with AWS Builder ID` でログインします。AWS Builder ID は個人のアカウントです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/e6676794-4ef9-502e-911d-1c5d5f26e124.png)

次に AWS アカウント ID を入力して CodeCatalyst の環境を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/2235b925-4d11-cb9f-5d74-8434a110c328.png)

以下の表示が出たら CodeCatalyst に戻ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/f33d3766-0c8c-2042-5e57-7d6fbc6fc10d.png)

`Create your first project` を押して CodeCatalyst のプロジェクトを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/65ace210-579a-35b1-1333-b72e9b04182e.png)

３種類から選べます。テンプレート（ブループリント）から始める、既存の Git リポジトリを持ってくる、ゼロからスクラッチで始める。といったところでしょうか。

今回は `Start with a blueprint` でテンプレートから選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/e37683bc-5814-3916-e059-c4318c7404fb.png)

テンプレートを選択すると説明が表示されるのでご自身の用途に合わせて選択してください。今回は `Single-page application` で進めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/35b73cfa-6c4f-fb53-143d-854fe9030436.png)

次にプロジェクト設定をします。

`Project details` では名前を決めて Git リポジトリを選択します。今回は CodeCatalyst で進めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/433c7d81-84d1-6d87-a031-29755f7bc7a0.png)

選択したテンプレートによって内容は変わると思いますが、フレームワークや CI/CD ワークフローを選択できるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/df7a72e6-0afe-ef6c-9d07-e27dfc3948ce.png)

AWSアカウントIDはプロジェクト作成時に選択したものが表示されているはずです。CodeCatalyst 用の IAM role を作成し、付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/17622eed-3de3-0580-c3c7-07f1b0fb66c1.png)

`Trust policy`
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CodeCatalyst",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "codecatalyst-runner.amazonaws.com",
          "codecatalyst.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

`Inline policy`
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "amplify:*",
        "cloudformation:*",
        "ecr:*",
        "ssm:*",
        "s3:*",
        "iam:Get*",
        "iam:PassRole",
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:TagRole",
        "iam:UpdateRole",
        "iam:AttachRolePolicy",
        "iam:DetachRolePolicy",
        "iam:PutRolePolicy",
        "iam:CreatePolicy",
        "iam:DeletePolicy",
        "iam:CreatePolicyVersion",
        "iam:DeletePolicyVersion",
        "iam:PutRolePermissionsBoundary",
        "iam:DeleteRolePermissionsBoundary",
        "sts:AssumeRole",
        "sts:GetCallerIdentity"
      ],
      "Resource": "*"
    }
  ]
}
```


リージョンを選択します。2024/06/22 時点では日本のリージョンは選択できません。早く来てほしいですね。今回は us-west-2（オレゴン）にしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/4b83483e-522e-a9c5-50f1-cae77bdea614.png)


その他、テンプレートのシステム構成だったり、生成するプロジェクトのプレビューを見られたりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/bb65c972-4f34-1799-3d45-74c2969692c6.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/6e601279-4335-d2c1-96b8-ac264f4acbd4.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/a1154965-64bd-ff66-e2d6-5e6d3ab97a96.png)

CodeCatalyst の環境準備が整ったら `Create project` を押してプロジェクトを作成しましょう。


# CodeCatalyst で開発をしてみる

### まずはリポジトリを手元に持ってきます。

`Clone repository` を押して Git の `HTTPS clone URL` をコピーしてローカルPCのコマンドラインで実行します。パスワードを問われますので `Personal access token（PAT）` を生成してコピーしパスワードとして入力してください。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/2a5ffa8c-ada8-0a93-0292-701f8a3df4ea.png)

```bash
local:~/dev/prac$ git clone https://[ユーザー名]@git.us-west-2.codecatalyst.aws/v1/[ユーザー名]/[CodeCatalystプロジェクト名]/[リポジトリ名]
Cloning into '[リポジトリ名]'...
Password for 'https://[ユーザー名]@git.us-west-2.codecatalyst.aws':

remote: Counting objects: 41, done.
Unpacking objects: 100% (41/41), 25.94 KiB | 171.00 KiB/s, done.
```

`Dev Environments（開発環境）` を利用すればローカルに開発環境を準備せずとも AWS Cloud9 を使って開発することもできるようです。今回はローカルで開発します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/550a52ae-c0db-039f-f172-5ff2d37169f2.png)



### 次に Issue を切ってブランチを作成し、ソースコード修正したものを PR 提出します。

Issue を作成すると、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/19921e7e-7a18-89f2-88d4-1f4d0782a14a.png)

Issues のボードに並びました。 `Todo` > `In progress` > `In review` > `Done` というステータスで管理できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/18dce165-c9d4-7254-5668-947536723e1a.png)

Atlassian の Jira / Bitbucket のようにチケットからブランチが切れるかと思いましたがどうやらできないようなのでローカルで `isssue/1` というブランチを切ります。簡単な修正をして Push します。ここで少し手間だなと思ったのが前述のパスワード（PAT）を都度生成してコピー＆ペーストしないといけないことです。SSH 鍵おけたりしないんでしょうかね。後日調べてみてできそうなら追記します。

さて、ローカル作業が終わったので CodeCatalyst に戻るとブランチが作られています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/2e4fc9e7-9480-6ad0-18d1-1948871e0cf0.png)


Pull request を提出してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/3e744fc8-86e4-5df9-b249-d103467bcf66.png)

差分も表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/45b17be5-4dc6-e199-15d6-ba15aedfb238.png)

本来はここでレビューなどを行いますが今回は PR を `Fast forward merge` でマージします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/acc65e4b-12af-317f-9507-174572eade18.png)

そうすると CI/CD パイプラインが PR をきっかけに動いています。これはテンプレートが準備してくれているものです。ビルドとテストが実行されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/94d065be-cab7-fc8a-3c82-6e6e9e8c3654.png)



`onPullRequestBuildAndTest.yaml` 
```yaml
Name: onPullRequestBuildAndTest
SchemaVersion: "1.0"
Triggers:
  - Type: PULLREQUEST
    Branches:
      - main
      - develop
    Events:
      - OPEN
      - REVISION
Actions:
  BuildAndTest:
    Compute:
      Type: Lambda
      Fleet: Linux.x86-64.Large
    Identifier: aws/build@v1
    Inputs:
      Sources:
        - WorkflowSource
    Outputs:
      Artifacts:
        - Name: build
          Files:
            - build/**/*
      AutoDiscoverReports:
        ReportNamePrefix: Test
        IncludePaths:
          - coverage/**
          - reports/**
    Configuration:
      Steps:
        - Run: npm install
        - Run: npm test -- --coverage --watchAll=false --testResultsProcessor="jest-junit"
        - Run: npm run build
Compute:
  Type: Lambda
  Fleet: Linux.x86-64.Large

```

左メニューの `Reports` からテストカバレッジも確認でき、便利そうですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/5177c993-aae4-cb4f-5654-d3b419464258.png)


# Amazon Q（生成AI）を使ってみる

### Amazon Q を有効にする

CodeCatalyst の目立つ位置に `Add with Amazon Q` というボタンがあるのでクリックしてください。右側にチャットが出てきて生成AIと対話できます。今は英語ですが先日の AWS Summit Japan 2024 のキーノートで Amazon Q が日本語対応すると発表されていたので近い内に日本語で使えると思います。楽しみですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/dc4a7ec5-661d-7100-cd39-eb579b8df728.png)


次に Issue を元に Amazon Q（生成AI）がソースコードの作成をしてくれる機能を使ってみます。Issue を作成する際に Assigners で `Assign to Amazon Q` を選びます。しかし、CodeCatalyst スペースの生成AIへのアクセス権の設定をしていないと利用できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/794ec897-c065-06b3-3b3f-58d5670a9854.png)

> Your space doesn't have access to the generative AI features of Amazon CodeCatalyst. Only users with the Space administrator role can enable access to these features.
スペースには、Amazon CodeCatalyst の生成 AI 機能へのアクセス権がありません。スペース管理者ロールを持つユーザーのみが、これらの機能へのアクセスを有効にできます。

CodeCatalyst スペースの生成AIへのアクセス権の設定ページへ `CodeCatalyst のトップページ` > `Settings` > `Generative AI` でたどり着きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/1eb481b9-d037-cdeb-486f-f2da4c55ea75.png)


> You can grant access to the generative AI features in Amazon CodeCatalyst for users in this space who have Amazon Q Developer subscriptions. For more information, see Pricing . Generative AI features require the use of services in other AWS Regions and, if applicable, will require that your data is sent to another AWS Region. By enabling generative AI features in Amazon CodeCatalyst, you consent to such cross-Region calls.
Amazon Q Developer サブスクリプションを持つこの分野のユーザーに、Amazon CodeCatalyst の Generative AI 機能へのアクセスを許可できます。詳細については、「料金表」を参照してください。Generative AI 機能を使用するには、他の AWS リージョンのサービスを使用する必要があり、該当する場合は、データを別の AWS リージョンに送信する必要があります。Amazon CodeCatalyst で Generative AI 機能を有効にすると、このようなクロスリージョン呼び出しに同意したことになります。

（参考）
https://aws.amazon.com/jp/q/developer/pricing/
https://codecatalyst.aws/explore/faq


### CodeCatalyst で Issues を立てて Amazon Q で Amplify Gen2 のソースコードを自動生成します

さて、本題です。Amazon Q（生成AI）に Amplify Gen2 のソースコードを作ってもらおうと思います。依頼内容は以下です。英語に翻訳して Issue を切ります。

Amplify Gen2の設定ファイルを作成する
1. フロントエンドは React で Amplify Hosting を利用する
2. バックエンドは DynamoDB を利用し API で通信する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/60afe358-44c8-027d-ddbe-56ce40527dca.png)


Issue を作成すると Amazon Q がプログラムを開発し始めました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/0c16eabc-bdca-bd7c-1d4f-33d9ec45a40a.png)

今回は Amazon Q と対話しながらタスクを進めるようにしていますので一歩づつ進んでいきます。

タスクの背景を説明したり、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/f084a50d-c43c-2a00-de1a-7d6e7f2d4dbc.png)

具体的な作成方針を説明してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/80fed4fc-027b-db4f-be0c-274adeba3926.png)

Reply で生成AIに細かい指示を出すこともできます。今回はこのまま進めるので `Proceed` を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/db93b036-f58c-8bda-da8d-cfb15bba70aa.png)

しばらくすると、ソースコードが生成されて Pull Request が作られています。素晴らしいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/292b2306-5128-6f6f-020b-3948a6c03e9e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/7ef4ef88-f3dd-2e03-5110-83bbbd703736.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/a9200739-c3aa-0d46-9b91-2a0b1dca9a8f.png)


### はたしてこれは正しいソースコードなのでしょうか？
生成AIは必ずしも正しいアウトプットを出すとは限りません。ここからは人の目で判断をしていくしか無いと思います。

ここからは CodeCatalyst と Amazon Q の話からは路線を変えて、Amplify Gen2 の話をしていきます。

# AWS Amplify Gen2 とは

### Amplify Gen2（第二世代）はフルスタック TypeScript になった

2024/5/6 に Amplify Gen2 が一般提供（GA）されました。
Gen2 とは Generation2（第二世代）のことであり、これまでの Amplify が進化したよ、ということです。

https://aws.amazon.com/jp/about-aws/whats-new/2024/05/aws-amplify-gen-2-available/

これまでの Gen1 はバックエンドの構築は CLI ベースでしたが Gen2 では __バックエンドを TypeScript の CDK をベースにコードファーストでの開発ができるようになります__。私は Amplify Gen1 を使うときはフロントエンドのホスティングと認証は利用しつつも、バックエンドは Amplify Gen1 で未対応の機能を実装しようとすると手詰まりしてしまうので別物として開発していました。

Gen2 ではフロントエンドもバックエンドも両方とも TypeScript で開発できるということで期待をしておりました。AWS Summit Japan 2024 でも Amplify Gen2 の話をたくさん聞きまして、早く使ってみたいという気持ちが高まりました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/f12d0320-7de5-210c-fa2f-008867bf0ce4.png)

（出典）https://aws.amazon.com/jp/amplify/

※参考までに過去 Amplify Gen1 について書いた記事も貼っておきます。

https://qiita.com/t-kurasawa/items/23ee71341df6b37ff7cc

https://qiita.com/t-kurasawa/items/3275d37053f4b0bea983

https://qiita.com/t-kurasawa/items/152bbda746e4658c3fc9

https://qiita.com/t-kurasawa/items/0d688b85ef7f9136e23b


### さて、ここからは実際に手を動かして Amplify Gen2 の理解を深めたいと思います。

公式チュートリアルを元に進めていきます。

https://docs.amplify.aws/react/start/quickstart/

先程まで作っていた CodeCatalyst のテンプレートを一度破棄します。チュートリアルの [`Create repository from templete`](https://docs.amplify.aws/react/start/quickstart/#1-create-the-repository) にソースコードを置き換えます。先ほどまでは Create React App（CRA）でしたが、Gen2 のテンプレートは Vite になっています。

AWS Amplify にデプロイします。CodeCatalyst のリポジトリを選択したいのですが選択肢にありませんでした。（2024/06/22時点）

仕方ないので GitHub や Bitbucket にリポジトリを引っ越します。本記事ではやりませんが CodeCatalyst からソースコード連携するパイプラインなどを組めば自動化できると思いますが今回は手動のお引越しです。残念。

Git リポジトリを Amplify とつなげます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/18feb438-97ed-fa10-6198-ea4efbf185c9.png)

アプリのデプロイが開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/40618418-7586-64e1-e11b-7c6eb9fd7566.png)


Amplify にデプロイされました。フロントエンドは Vite / React で裏側は DynamoDB となっている Todo アプリです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/d212942a-ed7d-ce5b-951f-ec07efd8d11c.png)

### Amplify Gen2 のテンプレートソースコードを眺めてみます

Gen2 ではバックエンドは `amplify` フォルダ配下に配置されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/fdc71d76-1d1e-7ed0-04c7-e428e33d2cba.png)

Amplify Gen2 のバックエンドを定義するファイルです。
認証やデータアクセスのリソース定義を `auth` や `data` 配下に `resource` ファイルを作り管理しています。

`backend.ts`
```JavaScript
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';

defineBackend({
  auth,
  data,
});

```

データアクセスのリソース管理を行うファイルです。Gen1 と比べて TypeScript のコードで記述されているため圧倒的にわかりやすいですね。ここの型定義をフロントエンドでも使えるということで Gen2 の注目機能はここだと思っています。

`data/resource.ts`
```JavaScript
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";

const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
    })
    .authorization((allow) => [allow.publicApiKey()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "apiKey",
    // API Key is used for a.allow.public() rules
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
  },
});

```

Cognito のメール認証の設定は以下のようになります。かんたんですね。

`auth/resource.ts`

```JavaScript
import { defineAuth } from '@aws-amplify/backend';

/**
 * Define and configure your auth resource
 * @see https://docs.amplify.aws/gen2/build-a-backend/auth
 */
export const auth = defineAuth({
  loginWith: {
    email: true,
  },
});

```


フロントエンドは `src` 配下にあります。ここは大きく変わらないかなと思いますが、バックエンドの型定義とフロントエンドの型定義を同一ソースコード内で管理できるのは良いですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/c64a0e16-0da1-aed3-8a1e-200b6a33d100.png)


### 他にも UI ライブラリやストレージなども進化している

本日の記事としては以上としますが UI ライブラリも進化しているようで React のコンポーネントと Amplify を組み合わせてかんたんに開発ができるようになってきているみたいです。この辺りも触ってみたら記事を書こうかなと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/c50842c6-a9b7-f001-cbc9-dbf72b9224c0.png)


# おわりに
`AWS Summit Japan 2024` に現地参加し、刺激を受けた２日間でした。生成AIのセッションが目白押しで、生成AIの技術情報のシャワーを浴びることができました。聞けなかったセッションのアーカイブ動画も見ていきたいと思います。

久しぶりにワクワクしたので熱が冷めない内に手を動かしてみて生成AIの手触り感・解像度が少しだけ上がりました。結局 Amplify Gen2 と CodeCatalyst, Amazon Q をつなげることができなかったので、本稿では別々に理解を進めることになってしまいましたがどちらも技術の進化を感じました。キーノートでは Amazon Q の日本語対応という発表もありましたので、これからはますます生成AIを使っていきたいです。

来年の AWS Summit も楽しみですね。ではまた。