旧MacをGitHubActionsのself-hosted runnersを使ってUnityのビルドマシンにする


![スクリーンショット_2022-08-13_10_29_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/7ee52100-ede9-e266-85b4-25ec4c209aba.png)


## 本記事について
Untyプロジェクトをビルドマシン、CIで自動ビルド & デプロイできたのでそのまとめ記事。
同様のことをやりたい人がいれば参考になるようにまとめる。
過程も書く。

## 背景
新しいMacbookを買った。
旧Macbookはまだ動くし、使い道はあるかなということで下取りには出さなかった。
(古くて下取りしても全然割引されないっていうのも大きい)
普段使いはしないけどビルドマシンとして活躍してほしい。

GameCIでもできるっぽいけど使ったことない。

## 環境

ビルドマシン
Macbook Pro Early 2015
メモリ 8GB
Intel Core i5

## 前提
- GitHub Actionsを使ったことがある。
- [[Unity]BatchModeでHelloWorld](https://qiita.com/Teach/items/ef5f4d135ac832ac5769)
- Command LineでXcodeのビルドができる(本記事では解説しない)
- Slackのwebhookのurl発行できる
- iosのビルドのみ扱う。

## self-hosted runnersとは
GitHub Acctionsのworkflowを自分の用意した環境で実行する仕組み。
自分のmacで動かせる。

- GitHubからローカルのPCを操作できる
- GitHubActionsのworkflowをローカルのPCで実行できる

という2つのニュアンスだとどちらも正しいと思う。
ただ、後者として捉えておくほうが良い気はする。

詳しくは公式ドキュメント見ていただければ。
https://docs.github.com/ja/actions/hosting-your-own-runners/about-self-hosted-runners

## ローカルのPCでself-hosted runnersで動かすメリット・デメリット

私の考え。

■ メリット

- 環境のカスタマイズがやりやすい
- 毎回のjob実行時にcleanしなくても良い。
- GitHub Actionsを使用する料金が無料
- バグった時の調査が楽

macOSはLinuxの10倍の枠を消費する。
https://docs.github.com/ja/billing/managing-billing-for-github-actions/about-billing-for-github-actions

■ デメリット
- PCの充電・起動が手間
- PCの置き場所が必要
- PCのスペックが低いと辛い

## STEP1 とりあえず実行してみよう

■ インストール

self-hosted runnersの使い方の手順はググるとたくさん出てくる。
が、難しくないのでサクッとやってしまえば良いと思う。
https://docs.github.com/ja/actions/hosting-your-own-runners/adding-self-hosted-runners


GitHubのプロジェクトに入る

Settings > Actions > Runners

New self-hostedrunner

以下のように選択

Runner image: mac OS
Architecture: x64 (siliconの場合はARM64)

するとコマンドが出てくるので上から順に実行していく

./config.shの部分の入力

```
name of runner group: そのままEnter -> Default
name of runner:  x64_mac
label: そのままEnter
work folder: そのままEnter
```

■ 実行
./run.shで待機状態にする。

```
actions-runner$ ./run.sh

√ Connected to GitHub
```

``` .github/workflows/build_ios_dev.yml

name: Build and Deploy Dev

on: workflow_dispatch

jobs:
  build-and-deploy:
    runs-on: self-hosted
    steps:
    - name: Test Working Directory
      run: pwd
    - name: end
      run: echo 'completed!'
```

まずはどこで実行されるかを調査してみる。

▷ 予想と結果
_work/{GitHubのアカウント名 or 組織名}/{リポジトリ名}
=> /Users/{User名}/actions-runner/_work/{リポジトリ名}/{リポジトリ名}

旧mac側でもpwdが流れる
=> 流れない。

```
Current runner version: '2.294.0'
2022-08-11 02:48:50Z: Listening for Jobs
2022-08-11 02:49:49Z: Running job: build-and-deploy
2022-08-11 02:49:56Z: Job build-and-deploy completed with result: Succeeded
```

![スクリーンショット_2022-08-13_10_42_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/080a5984-7e28-5a3e-75c9-9c27e33f31a2.png)

予想外な結果になった。
なぜこのdirectoryなのかは調べてもわからなかった。特に困ることはない。

## STEP2 checkoutしてみる

```.diff
  build-and-deploy:
    runs-on: self-hosted
    steps:
+    - uses: actions/checkout@v3
+      with:
+        clean: false
+    - name: Test Working Directory
+      run: ls
    - name: Test Working Directory
      run: pwd
    - name: end
```

https://github.com/actions/checkout

> Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching
    # Default: true
    clean: ''


cleanフラグがdefaultでtrueになっている。
それは不要なのでclean: falseにしている。

結果

動いた。

パスは
{リポジトリ名}/{リポジトリ名}/Assets

のように取得できた。ブランチはworkflow_dispatch実行時に指定したブランチ。

## STEP3 対象のリポジトリで手動でビルドできるかやってみる。
ScriptDefineSymbolsは手動で設定するように作っていたのでそれを設定。
Platformをiosに切り替えも手動でやる。
ビルド -> 動いた。

## STEP4 Slack通知の仕組みを作る。
この辺でもういけそうな気持ちになってきたので先に簡単そうなSlack通知を作る。

最初はwebhookでサクッと「ビルド成功しました」っていう文字を出すだけでいいかなと思っていたが、

以下の記事を見てかっこいいなと思ったので真似した。
https://zenn.dev/shonansurvivors/articles/fab832f7bfa8cebac24f


https://github.com/8398a7/action-slack

GITHUB_TOKENはenvで渡さなくても動いたので渡してない。

```.yml
    - uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        fields: repo,message,commit,ref,workflow,job,took
        author_name: iosビルド通知 dev
        fields: repo,message,commit,ref,workflow,took
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      if: always() # Pick up events even if the job fails or is canceled.
```

経過時間出てくれるのありがたい。

## STEP5 ビルドとデプロイする。

```.github/workflows/build_ios_dev.yml
name: Build and Deploy Dev

on: workflow_dispatch

jobs:
  build-and-deploy:
    runs-on: self-hosted
    steps:
    - uses: actions/checkout@v3
      with:
        clean: false
    - name: Clean
      run: make clean
    - name: Build Unity
      run: make unity-build-ios
    - name: Build Xcode
      run: make xcode-build
    - name: Deploy
      run: make deploygate-upload
    - uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        author_name: iosビルド通知 dev
        fields: repo,message,commit,ref,workflow,took
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      if: always() # Pick up events even if the job fails or is canceled.
```

経過時間とログを見やすくするために以下のプロセスは分離している。
- UnityからXcodeプロジェクトを出力
- Xcodeプロジェクトからipa書き出し。

Makefileは参考までに一部抜粋。

```Makefile
BUILD_DIR := build
UNITY_BUILD_IOS_PATH := $(BUILD_DIR)/ios/project
XCODE_PROJECT_PATH := $(UNITY_BUILD_IOS_PATH)/Unity-iPhone.xcodeproj
ARCHIVE_PATH := $(BUILD_DIR)/ios/temp/Unity-iPhone.xcarchive
IPA_DIR := $(BUILD_DIR)/ios/dest/
XCODE_EXPORT_OPTIONS_PLIST_PATH := BuildSettings/ios/ExportOptions.plist
UNITY_PATH := /Applications/Unity/Hub/Editor/2021.3.7f1/Unity.app/Contents/MacOS/Unity
BUILD_ENV := dev

...

.PHONY: clean
#: buildフォルダ消す
clean:
	rm -rf $(BUILD_DIR)

.PHONY: build-ios
build-ios: unity-build-ios xcode-build

.PHONY: unity-build-ios
unity-build-ios:
	$(UNITY_PATH) -batchmode -quit -projectPath . -logFile - \
	-executeMethod ProjectBuilder.BatchBuildiOS \
	-buildEnv $(BUILD_ENV) \
	-locationPath $(UNITY_BUILD_IOS_PATH)

.PHONY: xcode-build
xcode-build: xcode-clean xcode-archive
	xcodebuild -exportArchive -archivePath $(ARCHIVE_PATH) -exportPath $(IPA_DIR) -exportOptionsPlist $(XCODE_EXPORT_OPTIONS_PLIST_PATH)

.PHONY: xcode-clean
xcode-clean:
	xcodebuild clean -project $(XCODE_PROJECT_PATH) -target Unity-iPhone -configuration Release

.PHONY: xcode-archive
xcode-archive:
	xcodebuild -project $(XCODE_PROJECT_PATH) -scheme Unity-iPhone archive -archivePath $(ARCHIVE_PATH) -configuration Release -destination 'generic/platform=iOS'

.PHONY: deploygate-upload
deploygate-upload: set-deploygate-api-key
	curl \
	-H "Authorization: token $(DEPLOYGATE_API_KEY)" \
	-F "file=@$(IPA_DIR){プロジェクト名}.ipa" \
	-F "distribution_name=$(BUILD_ENV)" \
	-F "message=from mac" \
	"https://deploygate.com/api/users/{アカウント名}/apps"

.PHONY: set-deploygate-api-key
set-deploygate-api-key:
	$(eval DEPLOYGATE_API_KEY := $(shell cat config/secrets.json | jq -r .deploygate.api_key))
```

これで機能完成。

## STEP6 ビルドをちょっと早くする
並列化することで早くなるのでは？ということでやってみる

このmacについて > システムレポート

```
ハードウェアの概要:

  機種名:	MacBook Pro
  機種ID:	MacBookPro12,1
  プロセッサ名:	デュアルコアIntel Core i5
  プロセッサ速度:	2.7 GHz
  プロセッサの個数:	1
  コアの総数:	2
```

```
defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 2
```

時間

初回 16 min 24 sec
二回目 13 min 42 sec
並列化 13 min 12 sec

ちょっとは早くなったのでOK!



## 参考
https://framesynthesis.jp/tech/github/actions-unity/
https://llcc.hatenablog.com/entry/2016/01/15/235114

## 追記) 登録が消えていた場合

```
Failed to create a session. The runner registration has been deleted from the server, please re-configure.
```

以下で一度設定を消す

```
./config.sh remove
```

tokenの入力を求められる。このtokenは「New self-hostedrunner」を押すと出てくるtokenなのでそれを使う
そして、再度「New self-hostedrunner」の遷移先にあるコマンドを実行すればOK