【個人学習】AWS CDKとGitHubを使ったCI/CDパイプライン構築

>※ご注意
本記事は「とりあえず動けばOK！」をモットーにした個人学習のアウトプットとして書いています。
前提の環境情報や権限の詳細、セキュリティ設定などは省略している箇所があります。

## はじめに
### 今回の背景
以下の記事に動機を掲載しています。
詳しい背景は以下を参照ください

https://qiita.com/n0mura/items/bf553f7c61bd5ea720d4

### 本記事の目的
- 依存関係のセットアップからGitHub→AWSまでのCI/CDパイプライン構築の流れを示す
- 動かしてみた後での個人的理解度整理

## 手順実施後の状態
#### CI/CDパイプライン構築完了
- ローカル環境：開発者がコードを編集・コミット
- GitHub リポジトリ：push をトリガーに CI/CD（GitHub Actions 等）が動作
- AWS (us-east-1)：cdk deploy によってデプロイされるターゲット。現状は CDK Metadata だけを保持

```mermaid
flowchart LR
  subgraph dev["開発者ローカルPC"]
    A["ローカル環境"]
  end

  subgraph gh["GitHub CI/CD"]
    B["GitHub リポジトリ"]
  end

  subgraph aws["AWSアカウント"]
    subgraph cf["CloudFormation (us-east-1)"]
      s["CDK Stack<br>– ユーザー定義リソース: 0<br>– CDKMetadata のみ"]
    end
  end

  A -->|push| B
  B -->|"GitHub Actions<br>(cdk synth/deploy)"| cf
 
```

初回デプロイ`cdk bootstrap`が完了し、CloudFormationにてスタックのステータスが完了。
各リソースが作成されていること。
ユーザー定義リソースは、`CDKMetadata`のみ。

:::note
CDKToolkitは、AWS CDK の `cdk bootstrap` コマンドを実行したときに CloudFormation を使って 必ず作成される「ブートストラップ用の環境準備スタック」
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/db26810a-22bb-4d16-99fc-1012c7c33680.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/26535fca-f6e0-4010-8bbd-0c9c219c2203.png)


ローカルからリモートリポジトリへ`push`した際に、GitHubからAWS へデプロイされること
```
(.venv) PS C:\Users\XXXXXX> git push origin master
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/13ed69fb-4ce8-49ef-a1b4-d766b5079077.png)


#### 最終的なローカル環境

```mermaid
graph TD
    subgraph OS["ローカルPC（Windows 11）"]
        NVM["NVM for Windows<br/>v1.2.2"]
        Node["Node.js v22.15.0"]
        npm["npm v10.9.2"]
        CDK["AWS CDK CLI v2.1013.0"]
        AWSCLI["AWS CLI v2"]
        Git["Git v2.49.0"]
        gh["GitHub CLI (gh) v2"]
        Py["Python v3.12.10"]
        Pip["pip v25.0.1"]
        Venv["(.venv)"]
    end

    NVM    --> Node
    Node   --> npm
    npm    --> CDK
    CDK    --> AWSCLI
    Py     --> Pip
    Pip    --> Venv

    subgraph Project["ec2_avail_dash"]
        Init["cdk init<br/>(app.py, cdk.json, etc.)"]
        GitRepo["GitRepo初期化済み"]
    end

    Git    --> GitRepo
    gh     --> GitRepo
    AWSCLI --> Init
    CDK    --> Init
    Venv   --> Init
    GitRepo--> Init

    classDef exec fill:#fdebd0,stroke:#f5b041,stroke-width:2px;
    class Venv,GitRepo exec
```

#### 依存関係整理
```mermaid
graph TD
    subgraph OS["ローカルPC（Windows 11）"]
        NVM --> Node --> npm --> CDK --> AWSCLI
        Py --> Pip --> Venv
        Git --> GitRepo
        gh  --> GitRepo
    end
    subgraph Project["ec2_avail_dash"]
        GitRepo --> Init
        CDK     --> Init
        AWSCLI  --> Init
        Venv    --> Init
    end
```
| コンポーネント           | 説明                                                              |
|-------------------------|-------------------------------------------------------------------|
| NVM for Windows         | Windows 環境で使える Node.js のバージョン管理ツール。<br>特定のバージョンの Node.js をインストールできる。    |
| Node.js                 | JavaScript 実行環境。npm や AWS CDK CLI の実行に必要。                                  |
| npm                     | Node.js のパッケージマネージャ。ライブラリのインストール・管理を行う。                  |
| AWS CDK CLI             | AWS CDK アプリの synth/deploy を行う CLI ツール。                                      |
| AWS CLI                 | AWS アカウントとの認証設定および AWS API 呼び出しに利用。                        |
| Git                     | ソースコード管理ツール。リポジトリの初期化やコミット管理を行う。                        |
| GitHub CLI (gh)         | GitHub 上のリポジトリ作成やプルリクエスト操作を CLI から実行可能にするツール。          |
| Python                  | CDK（Python）アプリやスクリプト実行環境。                                              |
| pip                     | Python のパッケージマネージャ。venv 上へのライブラリインストールに利用。               |
| 仮想環境 (.venv)        | プロジェクト固有の Python 仮想環境。`pip install` で依存を隔離。                        |

## 手順


### １．ローカル環境セットアップ
#### 1-1.NVM for Windows インストール
#### 1-2.Node.js （LTS）インストール
#### 1-3.AWS CLI v2 インストール
認証情報設定
#### 1-4.Python インストール
 (任意)Python 仮想環境作成
#### 1-5.Git for Windows インストール
#### 1-6.AWS CDK v2 CLIインストール
```
npm install -g aws-cdk
```
### ２．CDK プロジェクト初期化
#### 2-1.プロジェクト用ディレクトリ作成
#### 2-2.CDK プロジェクト初期化
```
cd cdk init app --language python
```
#### 2-3.依存パッケージをインストール
```
pip install -r requirements.txt
```

#### CDK デプロイ確認
ここまで完了すれば、`cdk deploy`が可能

```c
#デプロイ前の生成内容確認コマンド
cdk synth

#現在のデプロイ済みスタックとcdk synthで生成されたテンプレとの差分確認
cdk diff

#初回デプロイ前に1度だけ実施すればOK
#CDK デプロイ時に利用する「ブートストラップ用リソース群」の初期セットアップ
cdk bootstrap aws://<ACCOUNT>/<REGION>

#cdk synth→CloudFormation実行→リソースのプロビを自動で行い、スタックをデプロイする
cdk deploy
```

`cdk deploy`実行後、CloudFormationスタックと各種リソースが作成される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/a104d8c9-2201-497c-826c-a34d7997b4fc.png)


### ３．Git/GitHub連携
#### 3-1.GitHub CLI(gh)のインストール
#### 3-2.GitHubリポジトリ作成 ＆ 初回push
GitHub連携設定
```
gh auth login
```
one-time codeを入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/1e9e842a-be5d-43cd-a6f6-eb613cd818aa.png)

設定完了画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/f7e612f2-5cd7-47e3-a44c-2eea646b685e.png)

ローカルPCからCLIでリポジトリ作成 & 初回push
```
gh repo create [リポジトリ名] --private --source=. --remote=origin --push
```

### ４．CI/CDパイプライン構築
#### 4-1.GitHubリポジトリにSecretsを設定
GitHubからAWSにデプロイ出来るよう、認証情報を設定する
**GitHub**
Settings > Secrets and variables > Actions > New repository secret
- AWS_ACCESS_KEY_ID：デプロイ用 IAM ユーザーのアクセスキー
- AWS_SECRET_ACCESS_KEY：シークレットキー

#### 4-2.GitHub Actions ワークフロー作成
- 目的：CI/CDの自動化
    - `master`にプッシュするだけでAWSにインフラ定義が反映される
- トリガー：`master`ブランチへのコードのプッシュ
- ジョブ：`ubuntu-latest`上で必要なパッケージをインストールし、`cdk deploy`を実行

<br>

リポジトリ直下に`.github/workflows/deploy.yml`を作成し、以下を記載する。
```yaml
name: CDK Deploy

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Install CDK CLI
        run: npm install -g aws-cdk@2.x

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install -r requirements.txt

      - name: CDK Deploy
        run: cdk deploy --require-approval never
        env:
          AWS_ACCESS_KEY_ID:     ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION:            us-east-1
          # AWS_ACCOUNT_ID:      ${{ secrets.AWS_ACCOUNT_ID }}  ← 設定していれば追加

```

#### CI/CDパイプライン動作確認

```
#スタック定義ファイルをadd
git add stack.py

#commit
git commit -m "コミットメッセージ"

#リモートリポジトリへpush
git push origin master

```

設定したGitHub Actionsの`master`ブランチへのプッシュをトリガーにデプロイが完了すればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/386b6e2c-7d91-4498-a973-830bdad3e009.png)


あとはAWSコンソールもしくはCLIで意図したリソースが作成されていればOK！
今回はS3バケットで確認

```python:スタック定義ファイル一部
 class Ec2AvailDashStack(Stack):
#略
        results_bucket = s3.Bucket(
            self,
            "AthenaResultsBucket",
            bucket_name="ec2-avail-dash-results",
            encryption=s3.BucketEncryption.S3_MANAGED,
            removal_policy=RemovalPolicy.DESTROY,
            auto_delete_objects=TRUE
        )
#略
```

S3コンソールから確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/af6cdc8f-a1bc-43e6-a05a-9b7713b8ae79.png)

CloudFormationコンソールから確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/b3092e3d-8b8d-49ee-9e21-a73e2a6ae560.png)


以上！

### 完了
これで冒頭の最終構成まで完了です。
ローカルでスタックファイルを編集して、リモートリポジトリへpushすると自動でAWSにデプロイされる仕組みが完成しました！

#### 感想
依存関係やバージョンの問題がいくつか実施している過程でぶつかりました。
整理してみてもなかなか覚えるのが難しそうですね（笑）

この機会にMermaid記法を使ってみたり、気になっていたGitHubとの連携も経験できて満足してしまいました。
次回は実用的なスタック定義からデプロイまでに挑戦してみたいと思います。

### 参考資料
https://nodejs.keicode.com/nodejs/how-to-use-nvm-windows.php

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/getting-started.html

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/strategy-cicd-litmus/understanding-cicd.html

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/bootstrapping.html

https://qiita.com/shun198/items/14cdba2d8e58ab96cf95

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/hello-world.html