マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~GitLab-CI編~ 

## CI/CD環境構築記事まとめ
- [マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~準備編~ ](https://qiita.com/kkbase515/items/eba4eebbf7a645caa7c8)
- [マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~GitLab、GitLab-Runner編~ ](https://qiita.com/kkbase515/items/d2d70671ef999cc47b59)
- マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~GitLab-CI編~ 
- マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~SSL化編~ （準備中）

## config.tomlを編集
デフォルトではジョブを起動した際、GitLabプロジェクトをクローンして処理を実行するため、minecraftのデータパックがあるディレクトリを参照できません。また、RCONやプライベートIPアドレスなど色々と設定が足りないです。
なので、minecraftのデータパックをCI/CD運用するための設定をconfig.tomlに追加します。

```config.toml
concurrent = 1
check_interval = 0
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "test"
  url = "http://gitlab"
  id = 2
  token = "<コピーしたトークン>"
  token_obtained_at = 2023-12-03T01:48:42Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  clone_url = "http://gitlab"
  #### 1. 環境変数を追記
  environment = ["HOST_IP=<プライベートIPアドレス（172.16.xxx.xxxや192.168.xxx.xxxなど）>", "RCON_PASSWORD=<パスワード>"]
  [runners.docker]
    tls_verify = false
    image = "docker:24.0.5"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    #### 2. ディレクトリをマウント
    volumes = ["/cache", "<minecraftのディレクトリ（server.jarがあるディレクトリ）>:/home/ec2-user/minecraft", "/usr/local/bin/mcrcon:/usr/local/bin/mcrcon"]
    network_mode = "gitlab_default"
    shm_size = 0
    network_mtu = 0
    #### 3. pull_policyを追加
    pull_policy = "if-not-present"
```

## 動作確認
config.tomlの設定が問題なくできているかを確認します。
.gitlab-ci.ymlに確認用のジョブを作成します。
``` .gitlab-ci.yml
test-mount:
  script: 
    - echo "This is mount test job"
    - ls -l
    - ls -l /home/ec2-user
    - ls -l /home/ec2-user/minecraft
    - ls -l /home/ec2-user/minecraft/world
    - echo $HOST_IP
```
ジョブ実行すると以下のように、minecraftのディレクトリが参照され、`$HOST_IP`の環境変数からサーバのプライベートIPアドレスが出力されることを確認してください。
もし、画像のような結果にならない場合は、どこか設定が誤っている可能性がありますので、設定内容を確認してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/9ac46fd7-edbd-679a-9d70-b1bf2075e1cb.png)

## RCON
データパックの反映にRCONを用います。

### mcrconをダウンロード 
GitHubのリリースページからmcrconをDLしてください。DLする際はOSに注意すること（minecraftサーバではなく、dockerイメージのOSに合わせること。基本debianなので、Linux版x86-64を選択すればよい）
また、ファイルは`config.toml`で設定したディレクトリにダウンロードすること（そのままコピペした場合は`/usr/local/bin/`にダウンロードすればよい）。
https://github.com/Tiiffi/mcrcon/releases

### server.propertiesを編集
minecraftサーバのrconを有効にします。
```server.properties
enable-rcon=true
rcon.password=<パスワード>
rcon.port=25575
```

### RCON動作確認
上記の設定が完了すれば、.gitlab-ciからRCONでサーバにコマンドを送信できるかを確認します
```.gitlab-ci.yml
test-rcon:
  image: amazonlinux:2023.4.20240416.0
  script: 
    - echo "This is rcon test job"
    - ls -l
    - ls -l /usr/local/bin
    - echo "RCONバージョン"
    - mcrcon -v
    - sleep 10
    - mcrcon -H $HOST_IP -P 25575 -p $RCON_PASSWORD 'say "RCONテストです"'
```
ジョブ実行すると、minecraftの画面にRCONから送信されたコマンドの結果が出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/d3956990-6049-9a49-5889-5e847c284a3f.png)

## データパックを自動デプロイ
では、本題のリソースパックの自動デプロイを行います。
.gitlab-ci.ymlにデプロイジョブを作成します。
```.gitlab-ci.yml
stages:
  - deploy
  - test

deploy-datapacks:
  stage: deploy
  image: amazonlinux:2023.4.20240416.0
  before_script: 
    - ls -l
    - yum install -y rsync
    - chmod 755 datapacks
    - ls -l /usr/local/bin/
  script: 
    - ls -l
    - echo "データパックを同期します"
    - rsync -auvz --delete ./datapacks home/ec2-user/minecraft/world/
    - mcrcon -v
    - echo "データパックをサーバに反映します"
    - mcrcon -H $HOST_IP -P 25575 -p $RCON_PASSWORD 'say "10秒後にデータパックを更新します"'
    - sleep 10
    - mcrcon -H $HOST_IP -P 25575 -p $RCON_PASSWORD 'reload'
```
ジョブの処理内容としては、rsyncコマンドでGitLabプロジェクトにあるデータパックをminecraftサーバに圧縮しつつコピーします。コピー後、RCONでリロードコマンドを送信するといったものです。

minecraftサーバに`testpack`というデータパックを読み込ませたいと思います。以下のようなfunctionを用意し、サーバリロード時にtellrawが実行されるようにしています。
```reload.mcfunction
### ロード時コメント
tellraw @a "testpack がロードされました"
```
ジョブを実行すると以下のようにデータパックが反映されます。
![deploy_datapack.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/cc55dd92-28af-4f49-dfcc-4b551857ea9f.gif)

## リソースパック反映
では、リソースパックも同様に設定していきます。
今回、データパックのプロジェクトをプライベートで作成していると思います。リソースパックは公開されたプロジェクトでないとリソースパックをDLすることは厳しいです。
ですので、リソースパック用の公開プロジェクトを作成するかデータパックのプロジェクトをプライベートからパブリックに変更するか、いずれかの対応が必要になります。

今回は公開プロジェクト用のプロジェクトを作成する方で対応します。データパックのプロジェクトを変更する場合は、`.gitlab-ci.yml`を編集するだけなので、簡単に設定できます。

### プロジェクト作成
[マイクラデータパック、リソースパック開発のCI/CD環境を構築 ~GitLab、GitLab-Runner編~]()と同様な流れでpublicなプロジェクトを作成します。

### リソースパック用のディレクトリを作成
リソースパックを管理するためのディレクトリを作成します。
ディレクトリ構造がすでに決まっている場合は、それに従っていただいて問題ないです。

### プロジェクト設定変更
プロジェクトを作成後、不要な権限は与えないようにします。基本的にRepositoryだけ有効でよいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/7c6deadb-173a-b47e-fea1-8a7db6640a12.png)

### プロジェクトにメンバーを追加
作成したプロジェクトにプッシュするためのデプロイユーザを追加します。
デプロイユーザを作成していない場合は、先に作っておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/c00f564c-773b-4740-1d91-4da7d879e83b.png)

### デプロイユーザのトークンを発行
ジョブ中にHTTP経由でプッシュする場合、ユーザのトークンが必要になります。
デプロイユーザの設定からAccess Tonkensより、write repositoryにチェックを入れてトークンを発行、発行されたトークンをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/6ebd11a2-0a65-5c34-aa0f-0a891294863f.png)

### リソースパックの設定を更新するジョブを作成
```.gitlab-ci.yml
deploy-resourcepack:
  stage: prepare
  image: amazonlinux:2023.4.20240416.0
  before_script: 
    - yum install -y wget
    - yum install -y git
    - cd /home/ec2-user
    - git clone http://<ユーザ名>:<ユーザのパスワード>@<サーバIPなど>/minecraft/resource-pack.git
    - cd resource-pack
    - cp -rp /builds/minecraft/test-project/resourcepacks /home/ec2-user/resource-pack/resourcepacks
    - git add .
    - git -c user.name='<ユーザ名>' -c user.email='<メールアドレス>' commit -m "fix resource packs"
    - git push http://<ユーザ名>:<ユーザ名>@<サーバIPなど>/minecraft/resource-pack.git main
    - export RESOURCE_PACK_DOWNLOAD_URL=http://<サーバIPなど>/minecraft/resource-pack/-/raw/main/resourcepacks/resource_pack.zip?ref_type=heads
    - export RESOURCE_PACK_LOCAL_DOWNLOAD_URL=http://$HOST_IP/minecraft/resource-pack/-/raw/main/resourcepacks/resource_pack.zip?ref_type=heads
    - wget -O resourcepack.zip $RESOURCE_PACK_LOCAL_DOWNLOAD_URL
    - export RESOURCE_PACK_SHA1=`sha1sum resourcepack.zip | awk '{ print $1 }'`
    - echo $RESOURCE_PACK_DOWNLOAD_URL
    - echo $RESOURCE_PACK_SHA1
  script: 
    - cd /home/ec2-user/minecraft
    - cat server.properties
    - sed '/^resource-pack=/d' server.properties > server.properties.bak
    - sed '/^resource-pack-sha1=/d' server.properties.bak > server.properties
    - cat server.properties
    - echo resource-pack=$RESOURCE_PACK_DOWNLOAD_URL >> server.properties
    - echo resource-pack-sha1=$RESOURCE_PACK_SHA1 >> server.properties
    - cp -p server.properties server.properties.bak
    - cat server.properties
  when: manual
```
少し複雑そうに見えて、やってることは以下の通りでシンプルです。
1. 非公開のプロジェクトにあるリソースパックのデータを公開プロジェクトにプッシュ
1. リソースパックDL用の環境変数を設定
1. リソースパックのハッシュ値の環境変数を設定
1. server.propertiesからresource-pack-sha1とresource-packの行を削除
1. server.propertiesにresource-pack-sha1とresource-packを追加

ジョブを実行してマイクラサーバを再起動すると、リソースパックが反映されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/e8723910-9b83-92ff-f00f-b8b2d2507152.png)

また、違うリソースパックを指定（RESOURCE_PACK_DOWNLOAD_URLは変更せず、リソースパックを上書き）してジョブを実行し、再起動すると違うリソースパックが反映されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/ba420d04-948a-21d7-0d9a-928b8390c2bb.png)

リソースパックに関しては、サーバの再起動を手動で行う必要がありますが（やろうと思えば、自動化可能）、データパックとリソースパックをコミット、プッシュすれば、自動でデプロイしてくれる環境が完成しました。

（CIと言いつつ、CIしてないのはナイショ。誰かが、コマンド実行タイプのlintツールを提供していただければテストステージがあるパイプラインを作れそうです。）


次はSSL化ですが、こちらに関しては少々お待ちください。