CIのActivateとかでライセンスを自動でActivateさせたい!
CIでUnityを扱う時はJenkinsとかであれば問題ないのですが、CircleCIやGitHub Actionsを使用するときにDockerでのライセンス認証では.ulfファイルというのが必要になってきます。
現在.ulfファイルをコマンドラインから生成することはできません。生成するにはブラウザ経由の一択です。
それを今回Puppeteerというnode.jsのツールを使って自動化してみました。
※今回の認証フローはPersonalEdition固定になります。
Puppetterとは、Webブラウザでの操作をソースコードから行えるものになります。
詳しくはこちら
Puppeteer
今回のリポジトリはこちら
MizoTake/unity-license-activate
実装
npm経由でPuppeteerを入れて以下のjsで実装しました。
今回はライセンスの認証が必要になるので https://license.unity3d.com/manual
のページで操作を行います。
手元にあるalfファイルから最終的にulfファイルをダウンロードする操作になります。
叩くコマンドは以下になります
node activate.js $email $password $alf_file_path
以下が今回のScriptの全容ですが細かく分けてどうなっているのか下で記述します。
const puppeteer = require('puppeteer')
const fs = require('fs')
;(async () => {
const browser = await puppeteer.launch()
const page = await browser.newPage()
const downloadPath = process.cwd()
const client = await page.target().createCDPSession()
await client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: downloadPath
})
await page.goto('https://license.unity3d.com/manual')
await page.waitForNavigation({
timeout: 60000,
waitUntil: 'domcontentloaded'
})
const email = `${process.argv[2]}`
await page.type('input[type=email]', email)
const password = `${process.argv[3]}`
await page.type('input[type=password]', password)
await page.click('input[name="commit"]')
await page.waitForNavigation({
timeout: 60000,
waitUntil: 'domcontentloaded'
})
const input = await page.$('input[name="licenseFile"]')
const alfPath = `${process.argv[4]}`
await input.uploadFile(alfPath)
await page.click('input[name="commit"]')
await page.waitForNavigation({
timeout: 60000,
waitUntil: 'domcontentloaded'
})
const selectedTypePersonal = 'input[id="type_personal"][value="personal"]'
await page.evaluate(
s => document.querySelector(s).click(),
selectedTypePersonal
)
const selectedPersonalCapacity =
'input[id="option3"][name="personal_capacity"]'
await page.evaluate(
s => document.querySelector(s).click(),
selectedPersonalCapacity
)
await page.click('input[class="btn mb10"]')
await page.waitForNavigation()
await page.click('input[name="commit"]')
let _ = await (async () => {
let ulf
do {
for (const file of fs.readdirSync(downloadPath)) {
ulf |= file.endsWith('.ulf')
}
await sleep(1000)
} while (!ulf)
})()
function sleep(milliSeconds) {
return new Promise((resolve, reject) => {
setTimeout(resolve, milliSeconds)
})
}
await browser.close()
})()
画面ごとの処理
// ライセンス認証を行うページに行く
await page.goto('https://license.unity3d.com/manual')
await page.waitForNavigation({
timeout: 60000,
waitUntil: 'domcontentloaded'
})
// ライセンス認証を行うページに飛ばしたがリダイレクトでUnityのログインページに飛んでいる
//コマンド引数からメールアドレスとパスワードをとってくる
const email = `${process.argv[2]}`
await page.type('input[type=email]', email)
const password = `${process.argv[3]}`
await page.type('input[type=password]', password)
// Sign inのボタンを押す
await page.click('input[name="commit"]')
↓
const input = await page.$('input[name="licenseFile"]')
// コマンドライン引数で指定したpathからfileを添付
const alfPath = `${process.argv[4]}`
await input.uploadFile(alfPath)
// Nextボタンを押す
await page.click('input[name="commit"]')
これでファイル添付ができてることがわかります。ファイル添付までできるのすげぇ…Puppeteer…
↓
// Personal Editionの選択
const selectedTypePersonal = 'input[id="type_personal"][value="personal"]'
await page.evaluate(
s => document.querySelector(s).click(),
selectedTypePersonal
)
// Personal Edition選択後に出てくるのOptionを選択
const selectedPersonalCapacity =
'input[id="option3"][name="personal_capacity"]'
await page.evaluate(
s => document.querySelector(s).click(),
selectedPersonalCapacity
)
// Nextボタンを押す
await page.click('input[class="btn mb10"]')
↓
// Download license fileボタンを押す
await page.click('input[name="commit"]')
// ダウンロードが始まるので手元に.ulfファイルができるまで待つ
let _ = await (async () => {
let ulf
do {
for (const file of fs.readdirSync(downloadPath)) {
ulf |= file.endsWith('.ulf')
}
await sleep(1000)
} while (!ulf)
})()
function sleep(milliSeconds) {
return new Promise((resolve, reject) => {
setTimeout(resolve, milliSeconds)
})
}
以上のような流れになっています。
さいごに
Puppeteer便利!!!!
await page.screenshot( {
path: "./example.png"
});
でScreenShotを撮りつつ実装してました。
ブラウザでしか行えない操作もこれがあればできるので色々と捗るんじゃないかなと思っています。
追記 (2019/12/11)
今回のScriptでは二段階認証を設定していると一度認証されているPCからでのみうまくいきます。
その辺をクリアしようと検証はしてますがまだうまくいかないので注意しつつ使用してみてください。