btp-setup-automatorを使ってVS CodeでCAPとFioriの開発をする

## はじめに
最近、ノートPCを買い替えました。BTPのための開発環境を一から作るのは手間なので、Dockerイメージ的なものが使えないかと考えていました。
2022年の[SAP Advent Calendar](https://adventar.org/calendars/7484)の記事「[SAP BTP 開発環境を Lima と WSL2 で作ってみる](https://zenn.dev/knsugiyama/articles/fcfc744745744c)」で、[btp-setup-automator](https://github.com/SAP-samples/btp-setup-automator)に開発で必要なツール等がインストールされていることを知ったので、これを使ってVS Codeで開発するための環境を作ってみることにしました。

## 環境
- Windows 11 Home
- VS Code

## 必要な設定
1. WSLを有効化
1. Docker Desktopをインストール
1. VS CodeにDev Conteinersをインストール
1. btp-setup-automatorで開発環境を作成

### 1. WSLを有効化
PowerShell、またはコマンドプロンプトで以下のコマンドを入力します。

```
wsl --install
```
再起動後、以下の画面が表示されるのでUNIXのユーザ、パスワードを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/7e7bc335-29c0-7a68-76ad-0aac2ec33a3a.png)

参考：https://learn.microsoft.com/en-us/windows/wsl/setup/environment

### 2. Docker Desktopをインストール
以下のURLからDocker Desktopのインストーラをダウンロードします。
https://www.docker.com/products/docker-desktop/
インストーラを実行し、ウィザードに沿ってインストールを進めます。インストールが完了するとショートカットからDocker Desktopを起動できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/7e34bc46-426b-0aa7-cca3-5741e57a8a23.png)
Resouces > WSL integrationで"**Enable integration with my default WSL distro**"にチェックが入っていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a458bd98-7974-ebd1-185c-dd3d086abb1e.png)

参考：https://docs.docker.com/desktop/install/windows-install/

### 3. VS CodeにDev Conteinersをインストール
コンテナの中で開発を行うため、VS Codeに[Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f72e47a5-cacf-1b18-6d98-dd2bd5a1e678.png)

#### Dev Containersの仕組み
Dev Containerでは、devcontainer.jsonという設定ファイルをもとに実行環境となるコンテナを作成します。devcontainer.jsonには使用するイメージやVS Codeの拡張などを指定します。事前に定義されそのまま使える設定もありますが、自分で設定ファイルを作ることもできます。

#### Quick start
以下のチュートリアルを実施すると、Dev Containersを使用する流れがわかります。
https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container

### 4. btp-setup-automatorで開発環境を作成
ここでは、以下のことをゴールとします。
- btp-setup-automatorで開発環境を作成する
- 作成した環境でCAPのプロジェクトとFioriアプリを作成する

#### 4.1. devcontainer.jsonを入手
以下のリポジトリに、btp-setup-automatorを設定するためのdevcontainer.jsonファイルがあります。
https://github.com/SAP-samples/btp-setup-automator/blob/main/.devcontainer/stable/devcontainer.json

#### 4.2. VS Codeで新規の開発環境を作成
開発で使用するためのディレクトリをローカル側（Dockerコンテナの外側）に作成します。

```:例
C:\Users\mio-f\projects\cap
```
作成したディレクトリをVS Codeで開き、.devcontainer/devcontainer.jsonファイルを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ff7cc2b8-7b20-b31b-a406-386c6b455abd.png)

1. で入手したdevcontainer.jsonの中身を貼り付けます。
```json:devcontainer.json
    // For format details, see https://aka.ms/devcontainer.json.
{
    "name": "BTP Setup Automator (Stable)",
    "image": "ghcr.io/sap-samples/btp-setup-automator:latest",
    "customizations": {
        "vscode": {
            "settings": {
                "python.defaultInterpreterPath": "/usr/local/bin/python3",
                "python.linting.enabled": true,
                "python.formatting.provider": "black",
                "python.linting.flake8Enabled": true,
                "python.linting.flake8Args": [
                    "--ignore=E501,F405,W504"
                ],
                "python.linting.pylintEnabled": false
            },
            "extensions": [
                "ms-python.python",
                "ms-python.vscode-pylance"
            ]
        },
        "codespaces": {
            "openFiles": [
                "parameters.json"
            ]
        }
    },
    "remoteUser": "user",
    "postCreateCommand": "cd /workspaces && echo 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.profile && pip install flake8 black && source ~/.profile",
    "workspaceFolder": "/workspaces",
    "hostRequirements": {
        "cpus": 2,
        "memory": "4gb",
        "storage": "32gb"
    }
}
```

**ポイント**
コピーしたファイルから以下の点だけ変更しています。もとは起動後に/home/userディレクトリが開く設定になっているのですが、現在開いているワークスペースを開くようにしたいため、最初に開くディレクトリを"/workspaces"に変更しています。
```
    "postCreateCommand": "cd /workspaces && echo 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.profile && pip install flake8 black && source ~/.profile",
    "workspaceFolder": "/workspaces",
```

#### 4.3. コンテナを起動
左下の"><"マークをクリックしてコマンドのリストを表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/dbaa3261-bbbb-e672-ace3-21de61f0bf3f.png)
リストから**Reopen in Container**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/06c6a661-db98-e318-2d97-cb82e78536b3.png)
コンテナが起動します。左下に接続先のコンテナが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e0e3d7be-a0c1-bb49-5b6f-102c30972f32.png)
Docker Desktopで見てみると、新しいコンテナが立ち上がっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/680fc1b3-71d8-75ee-feb6-31e43b2c6512.png)
"Inspect"タブで見ると、自分のローカルフォルダが"/workspace/cap"にマウントされていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/18040edf-4ba4-be78-0c25-3a5f8ee66107.png)

#### 4.4. CAPプロジェクトを登録
以下のコマンドでCAPのプロジェクトを登録します。

```
cd cap
cds init cap-sample
cd cap-sample
cds add sample-tiny //サンプルデータモデルを追加
```
プロジェクトが登録されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0595a910-1b7a-8ecb-460d-268461cd56a6.png)

`cds watch`で実行すると、いつものようにブラウザから`http://localhost:4004/`でアクセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ec3fc0a0-1d0d-9a93-9782-f21f4153815a.png)


#### 4.5. Fiori toolsの追加
CAPだけでなくFioriの開発もしたいので、Fiori toolsの拡張を追加します。

```json:devcontainer.json
            "extensions": [
                "ms-python.python",
                "ms-python.vscode-pylance",
                "sapse.sap-ux-fiori-tools-extension-pack" //追加
            ]
```

拡張を追加するときは、そのIdentifier（以下の赤枠部分）を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/1b2e13e3-826b-b9f7-aaa7-87013b861474.png)
devcontainer.jsonを変更するとコンテナをリビルドするか聞かれるので、"**Rebuild**"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5c97feb0-c6d0-6a06-2207-3e7cce2b9ef7.png)

リビルド後、Fiori toolsのコマンドが使えるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/711e889b-cc64-9700-e00d-9ae1b1cfd02e.png)

Application GeneratorでFioriアプリを作成しようとした際、以下のポップアップが出ました。デフォルトで選択されているオプション"Change owner /usr/local/lib to current user"を選択しても何も起こらなかったため、もう一つのオプション"**Set generators install location to /home.user/.application_wizard/generators**"を選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2e83b481-5d50-4065-776b-784962d25a07.png)

このあとはApplication Generatorを起動して普段通りFioriアプリを生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/1927ff48-1517-245c-fb98-504bccf1d96d.png)

Fioriアプリを実行することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ec72aecc-9d14-780d-0a88-b9ff4dc7fd2c.png)

**2023/7/28更新**
Pythonは使わないため、CAPとFioriの開発のために必要なツールのみ入れた状態が以下になります。

```json:devcontainer.json
{
    "name": "BTP Setup Automator (Stable)",
    "image": "ghcr.io/sap-samples/btp-setup-automator:latest",
    "customizations": {
        "vscode": {
            "settings": {
            },
            "extensions": [
				"sapse.sap-ux-fiori-tools-extension-pack",
				"humao.rest-client",
				"SAPSE.vscode-cds"
			]
        }
    },
    "remoteUser": "user",
    "postCreateCommand": "cd /workspaces && sudo npm install -g yo generator-easy-ui5",
    "workspaceFolder": "/workspaces"
}
```

## コンテナを使った開発の運用を検討してみる
コンテナを使った開発を今後どうしていくのがよいか、少し考えてみました（用途を個人開発に限定します）。考えられる方法は次の3つです。

### ①1つの設定で全てのBTP関連プロジェクトを管理
今回作成したルートフォルダにプロジェクトを追加していく方法です。

```
ルートフォルダ
├── .devcontainer
│   └── devcontainer.json
├── プロジェクト1
├── プロジェクト2
└── プロジェクトN
```

メリット：devcontainerの設定が1つでよい
デメリット：VS Codeのワークスペースにすべてのプロジェクトが表示され、見づらい

### ②同時に使用するプロジェクトごとにコンテナを立てる
同時に使用するプロジェクトごとにコンテナを立てる方法です。
```
プロジェクト1のルートフォルダ
├── .devcontainer
│   └── devcontainer.json
├── プロジェクト1.1
└── プロジェクト1.2

プロジェクト2のルートフォルダ
├── .devcontainer
│   └── devcontainer.json
├── プロジェクト2.1
└── プロジェクト2.2
```
メリット：ワークスペースが見やすい
デメリット：devcontainerの設定がプロジェクト（群）ごとに必要

### ③1つの設定で管理し、作業するプロジェクトだけ都度持ってくる
使用しないプロジェクトは「プロジェクトのプール」フォルダに置いておき、作業するプロジェクトだけをルートフォルダに持ってくる方法です。

```
ルートフォルダ
├── .devcontainer
│   └── devcontainer.json
└── プロジェクト1

プロジェクトのプール（コンテナの外）
├── プロジェクト2
└── プロジェクトN
```
メリット：devcontainerの設定が1つでよい、ワークスペースが見やすい
デメリット：プロジェクトを移動する手間がかかる

今後運用する中で変わる可能性はありますが、今のところ③の方法がよさそうな気がしています。