Загрузка данных


#!/bin/bash

set -euo pipefail

WORK_ROOT="$HOME/VMBuildAgent"

UNITY="/Applications/Unity/Hub/Editor/6000.3.6f1/Unity.app/Contents/MacOS/Unity"

APP_ID="${1:-}"

if [ -z "$APP_ID" ]; then
    echo "ERROR: app id required"
    exit 1
fi

if [[ ! "$APP_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
    echo "ERROR: invalid app id"
    exit 1
fi

JOB_DIR="$WORK_ROOT/working/$APP_ID"
PROJECT_DIR="$WORK_ROOT/projects/$APP_ID"
LOG_DIR="$WORK_ROOT/logs/$APP_ID"

JSON_FILE="$JOB_DIR/$APP_ID.json"
UNITYPACKAGE_FILE="$JOB_DIR/$APP_ID.unitypackage"

CREATE_LOG="$LOG_DIR/create_project.log"
IMPORT_LOG="$LOG_DIR/import_package.log"
PREPARE_LOG="$LOG_DIR/prepare_android.log"

READY_FILE="$PROJECT_DIR/prebuild_ready.txt"

if [ ! -x "$UNITY" ]; then
    echo "ERROR: Unity not found"
    echo "$UNITY"
    exit 1
fi

if [ ! -s "$JSON_FILE" ]; then
    echo "ERROR: JSON not found"
    echo "$JSON_FILE"
    exit 1
fi

if [ ! -s "$UNITYPACKAGE_FILE" ]; then
    echo "ERROR: UnityPackage not found"
    echo "$UNITYPACKAGE_FILE"
    exit 1
fi

PRODUCT_NAME=$(
    /usr/bin/plutil \
        -extract productName \
        raw \
        -o - \
        "$JSON_FILE"
)

PACKAGE_NAME=$(
    /usr/bin/plutil \
        -extract packageName \
        raw \
        -o - \
        "$JSON_FILE"
)

KEYSTORE_MODE=$(
    /usr/bin/plutil \
        -extract keystore.mode \
        raw \
        -o - \
        "$JSON_FILE"
)

if [ "$KEYSTORE_MODE" = "create" ]; then

    KEYSTORE_FILE="$JOB_DIR/$APP_ID.keystore"

    STORE_PASSWORD="${APP_ID}pass"
    KEY_ALIAS="${APP_ID}d"
    KEY_PASSWORD="${APP_ID}dpass"

elif [ "$KEYSTORE_MODE" = "existing" ]; then

    KEYSTORE_FILE=$(
        find "$JOB_DIR" \
            -maxdepth 1 \
            -type f \
            \( -iname "*.keystore" -o -iname "*.jks" \) \
            | head -n 1
    )

    if [ -z "$KEYSTORE_FILE" ]; then
        echo "ERROR: existing keystore not found"
        exit 1
    fi

    STORE_PASSWORD=$(
        /usr/bin/plutil \
            -extract keystore.storePassword \
            raw \
            -o - \
            "$JSON_FILE"
    )

    KEY_ALIAS=$(
        /usr/bin/plutil \
            -extract keystore.alias \
            raw \
            -o - \
            "$JSON_FILE"
    )

    KEY_PASSWORD=$(
        /usr/bin/plutil \
            -extract keystore.aliasPassword \
            raw \
            -o - \
            "$JSON_FILE"
    )

else

    echo "ERROR: unknown keystore mode: $KEYSTORE_MODE"
    exit 1

fi

if [ ! -s "$KEYSTORE_FILE" ]; then
    echo "ERROR: keystore not found"
    echo "$KEYSTORE_FILE"
    exit 1
fi

mkdir -p "$WORK_ROOT/projects"
mkdir -p "$LOG_DIR"

echo ""
echo "=================================="
echo " UNITY AGENT"
echo "=================================="
echo ""
echo "App ID: $APP_ID"
echo ""

echo "[1/5] Creating clean Unity project..."

rm -rf "$PROJECT_DIR"

"$UNITY" \
    -batchmode \
    -nographics \
    -quit \
    -createProject "$PROJECT_DIR" \
    -logFile "$CREATE_LOG"

if [ ! -d "$PROJECT_DIR/Assets" ]; then
    echo "ERROR: Unity project creation failed"
    echo "$CREATE_LOG"
    exit 1
fi

echo "OK"

echo ""
echo "[2/5] Importing UnityPackage..."

"$UNITY" \
    -batchmode \
    -nographics \
    -quit \
    -accept-apiupdate \
    -projectPath "$PROJECT_DIR" \
    -importPackage "$UNITYPACKAGE_FILE" \
    -logFile "$IMPORT_LOG"

if [ ! -d "$PROJECT_DIR/Assets" ]; then
    echo "ERROR: UnityPackage import failed"
    echo "$IMPORT_LOG"
    exit 1
fi

echo "OK"

echo ""
echo "[3/5] Creating Android preparation script..."

mkdir -p "$PROJECT_DIR/Assets/Editor"

cat > "$PROJECT_DIR/Assets/Editor/AutomaticAndroidPreparation.cs" <<'CSHARP'
using System;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;

public static class AutomaticAndroidPreparation
{
    public static void Prepare()
    {
        string appId = GetRequired("VM_APP_ID");
        string productName = GetRequired("VM_PRODUCT_NAME");
        string packageName = GetRequired("VM_PACKAGE_NAME");

        string keystorePath = GetRequired("VM_KEYSTORE_PATH");
        string storePassword = GetRequired("VM_STORE_PASSWORD");
        string keyAlias = GetRequired("VM_KEY_ALIAS");
        string keyPassword = GetRequired("VM_KEY_PASSWORD");

        Debug.Log("==================================");
        Debug.Log("AUTOMATIC ANDROID PREPARATION");
        Debug.Log("==================================");

        Debug.Log("App ID: " + appId);
        Debug.Log("Product Name: " + productName);
        Debug.Log("Package Name: " + packageName);
        Debug.Log("Keystore: " + keystorePath);
        Debug.Log("Alias: " + keyAlias);

        if (!File.Exists(keystorePath))
        {
            throw new Exception("Keystore not found: " + keystorePath);
        }

        Debug.Log("Switching active build target to Android...");

        bool switched = EditorUserBuildSettings.SwitchActiveBuildTarget(
            BuildTargetGroup.Android,
            BuildTarget.Android
        );

        if (!switched)
        {
            throw new Exception("Failed to switch build target to Android");
        }

        Debug.Log("Android build target active.");

        PlayerSettings.productName = productName;

        PlayerSettings.SetApplicationIdentifier(
            NamedBuildTarget.Android,
            packageName
        );

        PlayerSettings.Android.useCustomKeystore = true;

        PlayerSettings.Android.keystoreName = keystorePath;
        PlayerSettings.Android.keystorePass = storePassword;

        PlayerSettings.Android.keyaliasName = keyAlias;
        PlayerSettings.Android.keyaliasPass = keyPassword;

        EditorUserBuildSettings.buildAppBundle = true;

        AssetDatabase.SaveAssets();

        Debug.Log("");
        Debug.Log("Current version values:");
        Debug.Log("Version Name: " + PlayerSettings.bundleVersion);
        Debug.Log(
            "Version Code: " +
            PlayerSettings.Android.bundleVersionCode
        );

        Debug.Log("");
        Debug.Log("Final settings:");
        Debug.Log("Build Target: " + EditorUserBuildSettings.activeBuildTarget);
        Debug.Log("Product Name: " + PlayerSettings.productName);
        Debug.Log(
            "Package Name: " +
            PlayerSettings.GetApplicationIdentifier(
                NamedBuildTarget.Android
            )
        );
        Debug.Log(
            "Custom Keystore: " +
            PlayerSettings.Android.useCustomKeystore
        );
        Debug.Log(
            "Keystore: " +
            PlayerSettings.Android.keystoreName
        );
        Debug.Log(
            "Alias: " +
            PlayerSettings.Android.keyaliasName
        );
        Debug.Log(
            "Build App Bundle: " +
            EditorUserBuildSettings.buildAppBundle
        );

        string readyFile = Path.Combine(
            Directory.GetCurrentDirectory(),
            "prebuild_ready.txt"
        );

        File.WriteAllText(
            readyFile,
            "READY\n" +
            "id=" + appId + "\n" +
            "productName=" + productName + "\n" +
            "packageName=" + packageName + "\n" +
            "keystore=" + keystorePath + "\n" +
            "alias=" + keyAlias + "\n"
        );

        Debug.Log("");
        Debug.Log("ANDROID PROJECT PREPARED SUCCESSFULLY");
    }

    private static string GetRequired(string name)
    {
        string value = Environment.GetEnvironmentVariable(name);

        if (string.IsNullOrEmpty(value))
        {
            throw new Exception(
                "Missing environment variable: " + name
            );
        }

        return value;
    }
}
CSHARP

echo "OK"

echo ""
echo "[4/5] Preparing project for Android..."

rm -f "$READY_FILE"

export VM_APP_ID="$APP_ID"
export VM_PRODUCT_NAME="$PRODUCT_NAME"
export VM_PACKAGE_NAME="$PACKAGE_NAME"

export VM_KEYSTORE_PATH="$KEYSTORE_FILE"
export VM_STORE_PASSWORD="$STORE_PASSWORD"
export VM_KEY_ALIAS="$KEY_ALIAS"
export VM_KEY_PASSWORD="$KEY_PASSWORD"

"$UNITY" \
    -batchmode \
    -nographics \
    -quit \
    -accept-apiupdate \
    -projectPath "$PROJECT_DIR" \
    -executeMethod AutomaticAndroidPreparation.Prepare \
    -logFile "$PREPARE_LOG"

if [ ! -f "$READY_FILE" ]; then
    echo ""
    echo "ERROR: Android preparation failed"
    echo ""
    echo "Log:"
    echo "$PREPARE_LOG"
    exit 1
fi

echo "OK"

echo ""
echo "[5/5] Checking prepared project..."

if [ ! -d "$PROJECT_DIR/Assets" ]; then
    echo "ERROR: Assets folder missing"
    exit 1
fi

if [ ! -d "$PROJECT_DIR/ProjectSettings" ]; then
    echo "ERROR: ProjectSettings folder missing"
    exit 1
fi

echo "OK"

echo ""
echo "=================================="
echo " PROJECT READY FOR MANUAL CHECK"
echo "=================================="
echo ""
echo "ID:            $APP_ID"
echo "Product Name:  $PRODUCT_NAME"
echo "Package Name:  $PACKAGE_NAME"
echo "Keystore Mode: $KEYSTORE_MODE"
echo "Keystore:      $KEYSTORE_FILE"
echo "Alias:         $KEY_ALIAS"
echo ""
echo "Project:"
echo "$PROJECT_DIR"
echo ""
echo "Preparation log:"
echo "$PREPARE_LOG"
echo ""
echo "BUILD WAS NOT STARTED."
echo ""