12
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Unity + GitHub Actions】UnityPackageの生成からリリースまですべて自動化する

Last updated at Posted at 2021-05-25

実現する事

対象ブランチにコミットするだけで下記の処理を自動で行います。

  1. コミット情報を元にバージョンを決定 (Semantic Versioning)
  2. バージョンをpackage.jsonに書き込み
  3. コミットにバージョンのタグを設定
  4. unityPackageを生成
  5. GitHubのReleasesページにコミットメッセージと合わせて出力

下記のような感じになります。
自分でバージョンすら入力しないのでめちゃくちゃ楽になりました。

スクリーンショット 2021-05-24 17.29.15.png

[手順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をクリック
スクリーンショット 2021-05-25 14.04.02.png

スクリプトの編集画面になるのでactivation.ymlという名前でスクリプトを追加

スクリーンショット 2021-05-26 16.20.37.png

追加するスクリプト 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で保存します。
メッセージは何も書かなくても大丈夫です。

スクリーンショット 2021-05-26 0.24.32.png

Actionsに戻ると実行できるようになっているので「Run workflow」で実行 (2分程かかります)

スクリーンショット 2021-05-26 16.25.41.png

workflowをクリックして下記の画面まで進めます。完了するとArtifactsに「Unity_v2019.x.xf1.aif」というファイルが出力されているのでダウンロードします。

スクリーンショット 2021-05-26 16.29.54.png

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という名前でコピーしたものをペーストして登録
    スクリーンショット 2021-05-26 15.17.23.png

[手順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をクリック
スクリーンショット 2021-05-25 14.04.02.png

もしすでにworkflowがある場合は、下記のような表示になります。new workflowをクリック
スクリーンショット 2021-05-26 16.23.05.png

スクリプトの編集画面になるのでスクリプトを追加

スクリーンショット 2021-05-25 14.11.03.png

完了後、Start commit → commit changesで保存します。
メッセージは何も書かなくても大丈夫です。

スクリーンショット 2021-05-26 0.24.32.png

上記の手順で下記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

以上で完了です。適当にコミットしてテストしてみてください。

コミット時のメッセージのルール

img.png

タイプをつける

コミット時のメッセージに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 packagewith: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で一時的に動かないようにできます。
スクリーンショット 2021-05-26 0.33.40.png

プロジェクトのルートにAssetsフォルダが無い場合

release.ymlのBuild packagewith: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ボタンが表示されて手動実行できるようになります。
引数を渡す事も可能です。

スクリーンショット 2021-05-26 15.05.24.png

テストを実行したい

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に結果が出力されます。

スクリーンショット 2021-05-26 15.38.50.png

完了時にSlackに通知したい

下記を利用すると楽です。
https://github.com/8398a7/action-slack

1. SlackのWebhook URLを取得
ブラウザでSlackにログイン後、下記URLにアクセスし取得

2. リポジトリのSettings > SecretにSLACK_WEBHOOK_URLという名前でWebhook URLを登録
スクリーンショット 2021-05-26 15.17.23.png

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が無料で使えるか知りたい

GitHub 右上アイコン > Setting
スクリーンショット 2021-05-26 15.59.50.png

Billing&Planタブ > Usage this month > GitHub Actions

スクリーンショット 2021-05-26 16.00.05.png

GitHub Actionsについて効率良く学びたい

HTMLやJSのように、リポジトリのワークフローの内容は誰でも見る事ができます。
僕は、MessagePipeのbuild-release.ymlを大変参考にさせていただきました。
自分がよく見る好きなリポジトリを覗いてみてください。

各機能の詳細

参考

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?