LoginSignup
3
2

More than 5 years have passed since last update.

UnityCloudBuild API をPythonから利用してみた

Last updated at Posted at 2016-06-21

Unity Cloud BuildのAPIをPythonから利用してみました。他のシステムと連携してビルドしたファイルをアップロードする際に利用できるかなーと思います。

Unity Cloud Buildを利用してみた

BitBucket(旧:Stash)のソースコードからビルドできる点もポイントが高かったです。初期ビルドの設定はボタンぽちぽちで5分くらいだったので説明省略しています。

初回は手動でビルドして2回目以降をAPI経由で利用するといった用途を想定しています。今回利用するAPIの詳細は全て公式ドキュメントに記載されています。

1. ビルド実行

ビルドに失敗するとHTTPStatus:202が返ってきます。ビルド完了したファイルのURLは別ファイル

u.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import requests

API_TOKEN = "****"
ORGID = "****"
PROJECTS = "****"
BUILD_TARGETS = "****"


def get_url(func_name, extend=None):
    auth_base = "orgs/{orgid}/projects/{projectid}/buildtargets/{buildtargetid}".format(orgid=ORGID,
                                                                                        projectid=PROJECTS,
                                                                                        buildtargetid=BUILD_TARGETS)
    if extend:
        url_base = "https://build-api.cloud.unity3d.com/api/v1/{auth}/{func}{extend}"
        return url_base.format(auth=auth_base, func=func_name, extend=extend)

    url_base = "https://build-api.cloud.unity3d.com/api/v1/{auth}/{func}"
    return url_base.format(auth=auth_base, func=func_name)


def get_headers():
    return {
        "Content-Type": "application/json",
        "Authorization": "Basic {token}".format(token=API_TOKEN),
    }


def execute_build():
    """
    ビルド実行

    # 準正常系 既にビルド中
    [{"buildtargetid":"****","buildTargetName":"****","error":"Cannot start build - already a build pending."}] 202
    """
    response = requests.post(get_url("builds"), headers=get_headers(), data={})
    print(response.text), response.status_code
    return

# ビルド実行
execute_build()

2. ビルドステータス取得

ビルドステータスは次の通り { queued , sentToBuilder , started , restarted , success , failure , canceled , unknown }
無課金だとqueuedの時間が長いです。ビルド成功したらsuccessとなります

u.py

def get_builds():
    """
    最新の25件のビルド情報が取得できる。
    それより古いデータ取得したい時はper_pageとpageパラメータを修正すること
    """
    response = requests.get(get_url("builds"), headers=get_headers())
    print(response.text), response.status_code
    return


def get_build(number):
    """
    指定したビルド情報が取得できる

    # 準正常系
    存在しない場合は404 : {"error":"The requested object was not found."}

    :param number: int
    """
    response = requests.get(get_url("builds", extend="/" + str(number)), headers=get_headers())
    print(response.text), response.status_code
    return


def get_latest_build():
    """
    最新1件のビルドが取得できる
    """
    build_start_result = requests.get(get_url("builds", extend="?per_page=1&page=1"), headers=get_headers())
    print(build_start_result.text), build_start_result.status_code
    return

# 特定ビルド取得
get_build(6)

# 最新ビルド取得
get_latest_build()

# ビルド一括取得
get_build_status()

3. ビルドキャンセル

実装してから、APIからキャンセルしたいことなんて、あるのだろうか? と思いました。
HTMLのDELETEクエリーでキャンセルする仕様です。DELETEクエリーは今年初の利用。REST原則に忠実でAPI作ったエンジニアの性格が、なんとなく伝わりました。

u.py

def cancel_all():
    """
    全てのビルドをキャンセルする
    """
    response = requests.delete(get_url("builds"), headers=get_headers())
    print(response.text), response.status_code


def cancel(number):
    """
    特定ビルドをキャンセルする

    # 正常系 キャンセル成功
    204

    # 準正常系 存在しない
    {"error":"The requested object was not found."} 404

    # 準正常系 ビルド完了済みのビルドを指定したとき
    204

    :param number: int
    """
    response = requests.delete(get_url("builds", extend="/" + str(number)), headers=get_headers())
    print(response.text), response.status_code


# 特定ビルドキャンセル
cancel(7)

# 全ビルドキャンセル
cancel_all()

4. ダウンロードURL取得

ビルド成功したらS3にファイルがアップロードされます。ダウンロードするためのURLを取得するための関数です。

u.py

def get_latest_build_download_urls():
    """
    最新の成功したビルドのダウンロードURL

    :return: str
    """
    response = requests.get(get_url("builds", extend="?buildStatus=success&per_page=1&page=1"),
                                      headers=get_headers())
    data = ujson.loads(response.text)
    assert len(data) > 0
    return data[0].get('links').get('download_primary').get('href')

# 最新の成功したビルドのダウンロードURL
print get_latest_build_download_urls()

全部まとめた完成品のソース

u.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import requests
import ujson

API_TOKEN = "****"
ORGID = "****"
PROJECTS = "****"
BUILD_TARGETS = "****"


def get_url(func_name, extend=None):
    auth_base = "orgs/{orgid}/projects/{projectid}/buildtargets/{buildtargetid}".format(orgid=ORGID,
                                                                                        projectid=PROJECTS,
                                                                                        buildtargetid=BUILD_TARGETS)
    if extend:
        url_base = "https://build-api.cloud.unity3d.com/api/v1/{auth}/{func}{extend}"
        return url_base.format(auth=auth_base, func=func_name, extend=extend)

    url_base = "https://build-api.cloud.unity3d.com/api/v1/{auth}/{func}"
    return url_base.format(auth=auth_base, func=func_name)


def get_headers():
    return {
        "Content-Type": "application/json",
        "Authorization": "Basic {token}".format(token=API_TOKEN),
    }


def execute_build():
    """
    ビルド実行

    # 準正常系 既にビルド中
    [{"buildtargetid":"****","buildTargetName":"****","error":"Cannot start build - already a build pending."}] 202
    """
    response = requests.post(get_url("builds"), headers=get_headers(), data={})
    print(response.text), response.status_code
    return


def get_builds():
    """
    最新の25件のビルド情報が取得できる。
    それより古いデータ取得したい時はper_pageとpageパラメータを修正すること
    """
    response = requests.get(get_url("builds"), headers=get_headers())
    print(response.text), response.status_code
    return


def get_build(number):
    """
    指定したビルド情報が取得できる

    # 準正常系
    存在しない場合は404 : {"error":"The requested object was not found."}

    :param number: int
    """
    response = requests.get(get_url("builds", extend="/" + str(number)), headers=get_headers())
    print(response.text), response.status_code
    return


def get_latest_build():
    """
    最新1件のビルドが取得できる
    """
    build_start_result = requests.get(get_url("builds", extend="?per_page=1&page=1"), headers=get_headers())
    print(build_start_result.text), build_start_result.status_code
    return


def get_latest_build_download_urls():
    """
    最新の成功したビルドのダウンロードURL

    :return: str
    """
    response = requests.get(get_url("builds", extend="?buildStatus=success&per_page=1&page=1"),
                                      headers=get_headers())
    data = ujson.loads(response.text)
    assert len(data) > 0
    return data[0].get('links').get('download_primary').get('href')


def cancel_all():
    """
    全てのビルドをキャンセルする
    """
    response = requests.delete(get_url("builds"), headers=get_headers())
    print(response.text), response.status_code


def cancel(number):
    """
    特定ビルドをキャンセルする

    # 正常系 キャンセル成功
    204

    # 準正常系 存在しない
    {"error":"The requested object was not found."} 404

    # 準正常系 ビルド完了済みのビルドを指定したとき
    204

    :param number: int
    """
    response = requests.delete(get_url("builds", extend="/" + str(number)), headers=get_headers())
    print(response.text), response.status_code


# 特定ビルドキャンセル
# cancel(7)

# 全ビルドキャンセル
# cancel_all()

# 特定ビルド取得
# get_build(6)

# 最新ビルド取得
# get_latest_build()

# ビルド一括取得
# get_build_status()

# ビルド実行
# execute_build()

# 最新の成功したビルドのダウンロードURL
print get_latest_build_download_urls()

3
2
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
3
2