実現する事
対象ブランチにコミットするだけで下記の処理を自動で行います。
- コミット情報を元にバージョンを決定 (Semantic Versioning)
- バージョンをpackage.jsonに書き込み
- コミットにバージョンのタグを設定
- unityPackageを生成
- GitHubのReleasesページにコミットメッセージと合わせて出力
下記のような感じになります。
自分でバージョンすら入力しないのでめちゃくちゃ楽になりました。
[手順1] Unityのアクティベーション
GitHub ActionsでUnityを動かすにはアクティベーションが必要です。
こちらを参考にさせていただきました。
[注意点]
- アクティベーションは最初の1度のみ必要です。
- 今回の方法は、Personalライセンスの例です。Plus/Proライセンスの場合、GitHub上にUnityのID、パスワードを保存する為多少リスクがあります。UnityPackageを出力する用途であればPersonalライセンスを作った方が早いかもしれません。詳しくはこちら
- 今回の方法は、Unity2019.x用のやり方です。Unity2020.xでも使いたい場合は別途アクティベーションする必要があるようです。
1. [GitHub] アクティベーションファイルを取得
リポジトリのActionsタブ > set up a workflow yourselfをクリック
スクリプトの編集画面になるのでactivation.ymlという名前でスクリプトを追加
追加するスクリプト activation.yml
name: Acquire activation file
on: workflow_dispatch
jobs:
activation:
name: Request manual activation file 🔑
runs-on: ubuntu-latest
steps:
# Request manual activation file
- name: Request manual activation file
id: getManualLicenseFile
uses: game-ci/unity-request-activation-file@v2
# Upload artifact (Unity_v20XX.X.XXXX.alf)
- name: Expose as artifact
uses: actions/upload-artifact@v2
with:
name: ${{ steps.getManualLicenseFile.outputs.filePath }}
path: ${{ steps.getManualLicenseFile.outputs.filePath }}
完了後、Start commit → commit changesで保存します。
メッセージは何も書かなくても大丈夫です。
Actionsに戻ると実行できるようになっているので「Run workflow」で実行 (2分程かかります)
workflowをクリックして下記の画面まで進めます。完了するとArtifactsに「Unity_v2019.x.xf1.aif」というファイルが出力されているのでダウンロードします。
2. [Unity] アクティベーション
- license.unity3d.comにアクセス
- さきほどダウンロードしたUnity_v2019.x.xf1.aifを指定してアクティベートする
- 最終的に出力されるUnity_v2019.x.xf1.alf.zipをダウンロード
3. [GitHub] Secretsにダウンロードしたライセンスを登録
- Unity_v2019.x.xf1.alf.zipを解凍
- 解凍したUnity_v2019.x.ulfをテキストエディタで開いてコピーする
- リポジトリのSettings > SecretにUNITY_LICENSEという名前でコピーしたものをペーストして登録
[手順2] パッケージを生成するスクリプトを設置しコミット
下記スクリプトをAssets/Editor/に設置
パス : Assets/Editor/PackageExporter.cs
設置後、Unity上部のメニュー 「Tools > Export Unitypackage Test」
で問題無く出力できるかテストしてみてください。
問題無ければコミットしてください。
[変更箇所]
- RootDirectory: "パッケージまでのディレクトリ名を指定"
例) "Assets/Plugins/IDReference" - FileName: "プラグイン名を指定"(FileName.unitypackageという名前で出力されます)
例) "IDReference"
PackageExporter.cs
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class PackageExporter
{
public const string RootDirectory = "Assets/Plugins/IDReference";
public const string FileName = "IDReference";
/// <summary>
/// パッケージの書き出し(エディタ上でのテスト用)
/// メニュー 「Tools > Export Unitypackage Test」をクリックで実行
/// </summary>
[MenuItem("Tools/Export Unitypackage Test")]
public static void ExportTestOnEditor()
{
var exportPath = EditorUtility.SaveFilePanel
(
"保存先を選択",
Application.dataPath,
$"{FileName}.unitypackage",
"unitypackage"
);
CreatePackage(RootDirectory, exportPath);
}
/// <summary>
/// パッケージの書き出し
/// GitHub Actionsから呼ばれる
/// </summary>
public static void Export()
{
CreatePackage(RootDirectory, $"build/{FileName}.unitypackage");
}
public static void CreatePackage(string rootDirectory, string exportPath)
{
SafeCreateDirectory(exportPath);
var assetsPaths = GetAllAssetsAtPath(rootDirectory);
AssetDatabase.ExportPackage(assetsPaths, exportPath, ExportPackageOptions.Default);
Debug.Log($"Export complete: {Path.GetFullPath(exportPath)}\nExport below files:\n{string.Join("\n", assetsPaths)}");
}
public static DirectoryInfo SafeCreateDirectory( string path )
{
var diParent = Directory.GetParent(path);
if ( diParent == null || Directory.Exists( diParent.FullName ) )
{
return null;
}
return Directory.CreateDirectory( diParent.FullName );
}
public static string[] GetAllAssetsAtPath(string root)
{
return Directory.GetFiles(root, "*", SearchOption.AllDirectories)
.Where(x => !string.IsNullOrEmpty(x))
.Where(x => !x.EndsWith(".meta"))
.Where(x => x != ".DS_Store")
.ToArray();
}
}
[手順3] Actionsに.ymlファイルを追加
リポジトリのActionsタブ > set up a workflow yourselfをクリック
もしすでにworkflowがある場合は、下記のような表示になります。new workflowをクリック
スクリプトの編集画面になるのでスクリプトを追加
完了後、Start commit → commit changesで保存します。
メッセージは何も書かなくても大丈夫です。
上記の手順で下記2つのスクリプトを追加します。
update-package.yml
[変更箇所]
branches:
- 対象のブランチを指定 例) main
TARGET_FILE: 自分のパッケージのpackage.jsonがあるパスを指定
例) ./Assets/Plugins/IDReference/package.json
name: Update package.json
on:
push:
branches:
- main
env:
TARGET_FILE: ./Assets/Plugins/IDReference/package.json
jobs:
update-packagejson:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
# Checkout
- uses: actions/checkout@v2
- name: Output package.json (Before)
run: cat ${{ env.TARGET_FILE}}
# Cache
- name: Cache
uses: actions/cache@v2
with:
path: Library
key: Library-Package
restore-keys: Library-
# Get version
- uses: actions/checkout@v2
- name: Get next version
id: tag_version
uses: mathieudutour/github-tag-action@v5.5
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
dry_run: true
# Update
- name: Update package.json to version ${{ steps.tag_version.outputs.new_version }}
run: |
sed -i -e "s/\(\"version\":\) \"\(.*\)\",/\1 \"${{ steps.tag_version.outputs.new_version }}\",/" ${{ env.TARGET_FILE }}
# Check
- name: Check update
id: check_update
run: |
cat ${{ env.TARGET_FILE}}
git diff --exit-code || echo "::set-output name=changed::1"
# Commit
- name: Commit files
id: commit
if: steps.check_update.outputs.changed == '1'
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit -m "Update package.json to ${{ steps.tag_version.outputs.new_version }}" -a
# Push
- name: Push changes
if: steps.check_update.outputs.changed == '1'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
tags: true
release.yml
[変更箇所]
FILE_NAME: "パッケージ名を指定" 例) "IDReference"
BUILD_METHOD: "パッケージを生成するメソッドをnamespaceから指定"
例) "PackageExporter.Export"
[注意点]
Assetsフォルダがリポジトリのルートに無い場合は、後述している「プロジェクトのルートにAssetsフォルダが無い場合」を参照してください。
name: Release Unity Package
on:
workflow_run:
workflows:
- "Update package.json"
types:
- completed
env:
FILE_NAME: "IDReference"
BUILD_METHOD: "PackageExporter.Export"
jobs:
release:
name: Create Release
runs-on: ubuntu-latest
timeout-minutes: 15
if: ${{ github.event.workflow_run.conclusion == 'success' }}
strategy:
fail-fast: false
steps:
# Checkout
- name: Checkout repository
uses: actions/checkout@v2
with:
lfs: true
# Cache
- name: Cache
uses: actions/cache@v2
with:
path: Library
key: Library-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
restore-keys: |
Library-
# Build
- name: Build package
id: build
uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
buildName: ${{ env.FILE_NAME }}.unitypackage
targetPlatform: StandaloneLinux64
buildMethod: ${{ env.BUILD_METHOD }}
versioning: None
# Check .meta
- name: Check all .meta is commited
run: |
if git ls-files --others --exclude-standard -t | grep --regexp='[.]meta$'; then
echo "Detected .meta file generated. Do you forgot commit a .meta file?"
exit 1
else
echo "Great, all .meta files are commited."
fi
working-directory: Assets
# Versioning
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v5.5
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Create Release
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tag_version.outputs.new_tag }}
release_name: ${{ steps.tag_version.outputs.new_tag }}
body: ${{ steps.tag_version.outputs.changelog }}
draft: false
prerelease: false
# Upload Assets
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: build/${{ env.FILE_NAME }}.unitypackage
asset_name: ${{ env.FILE_NAME }}_${{ steps.tag_version.outputs.new_tag }}.unitypackage
asset_content_type: application/zip
以上で完了です。適当にコミットしてテストしてみてください。
コミット時のメッセージのルール
タイプをつける
コミット時のメッセージにfix:
などの決められたタイプをつける事でリリースノートに表示されます。言い替えると表示されたくないものは、 タイプをつけなければ良いです。
コミットメッセージとリリースノートの出力例
コミットメッセージ | リリースノート |
---|---|
fix: Test | Test(59e71d0) |
Update reslease.yml | 表示されない |
もちろんリリース後もリリースノートの修正はできるので何か問題あれば書き換えればいいや程度の認識で問題無いと思います。
タイプの書式
タイプ(スコープ): 修正または追加内容
タイプ: 修正または追加内容
例) fix(Enemy): 移動速度の修正
使えるタイプ一覧
タイプ | 説明 |
---|---|
feat: | 新機能の追加 |
fix: | バグの修正 |
docs: | ドキュメントの修正 |
style: | スタイルの調整(空白の削除など) |
refactor: | バグでもなく機能も追加しないコードの修正 |
perf: | パフォーマンスの向上に伴う修正 |
特殊なタイプ
BREAKING CHANGE:
破壊的な変更があった場合、記入する特殊なタイプ
例)
perf: ライブラリを一新
BREAKING CHANGE: 前バージョンとは互換性がありません。
How to的なもの
Unityバージョンを設定したい
今回のコードではUnityのバージョンを指定していません。指定していない場合はコミットしたUnityバージョンを使用します。
明示的に指定する場合は、release.ymlのBuild package
のwith:
にunityVersion: Unityのバージョン
を指定してください。
例) 2019.4.26f1
# Build
- name: Build package
id: build
uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
unityVersion: 2019.4.26f1 ← 追加
buildName: ${{ env.FILE_NAME }}.unitypackage
利用可能なUnityのバージョンを確認したい
下記で確認できます。見る感じ新バージョンへの対応は早いようです。
一時的にWorkflowを動かないようにしたい
Disable workflowで一時的に動かないようにできます。
プロジェクトのルートにAssetsフォルダが無い場合
release.ymlのBuild package
のwith:
にbuildsPath: Assetsまでのパスを指定
例) src/Unity
# Build
- name: Build package
id: build
uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
buildsPath: src/Unity ← 追加
buildName: ${{ env.FILE_NAME }}.unitypackage
手動でも実行したい
workflow_dispatch
を記述する事で簡単に使えます。
update-package.ymlを下記のように変更
on:
push:
branches:
- main
workflow_dispatch ←追加
Run workflowボタンが表示されて手動実行できるようになります。
引数を渡す事も可能です。
テストを実行したい
EdiorModeテストとPlayModeテストを同時に実行する例
name: Test project
on: workflow_dispatch
jobs:
testAllModes:
name: Test in ${{ matrix.testMode }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
testMode:
- playmode
- editmode
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/cache@v2
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}
restore-keys: |
Library-
- uses: game-ci/unity-test-runner@v2
id: tests
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
projectPath: ${{ matrix.projectPath }}
testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts
githubToken: ${{ secrets.GITHUB_TOKEN }}
checkName: ${{ matrix.testMode }} Test Results
- uses: actions/upload-artifact@v2
if: always()
with:
name: Test results for ${{ matrix.testMode }}
path: ${{ steps.tests.outputs.artifactsPath }}
完了後、Artifactsに結果が出力されます。
完了時にSlackに通知したい
下記を利用すると楽です。
https://github.com/8398a7/action-slack
1. SlackのWebhook URLを取得
ブラウザでSlackにログイン後、下記URLにアクセスし取得
2. リポジトリのSettings > SecretにSLACK_WEBHOOK_URLという名前でWebhook URLを登録
3. release.ymlの最後に下記コードを追加
- uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow,job,took # selectable (default: repo,message)
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required
if: always() # Pick up events even if the job fails or is canceled.
あと何分GitHub Actionsが無料で使えるか知りたい
Billing&Planタブ > Usage this month > GitHub Actions
GitHub Actionsについて効率良く学びたい
HTMLやJSのように、リポジトリのワークフローの内容は誰でも見る事ができます。
僕は、MessagePipeのbuild-release.ymlを大変参考にさせていただきました。
自分がよく見る好きなリポジトリを覗いてみてください。
各機能の詳細
- GitHub Actionの構文
- Unityのビルド game-ci/unity-builder
- バージョンの管理 mathieudutour/github-tag-action
- リリース actions/create-release