| 개요

 

keystore 정보는 ProjectSettings.asset 파일에 아래와 같이 저장된다. 

  AndroidKeystoreName: '{inproject}: Keystore/name.keystore'
  AndroidKeyaliasName: name
...중략...
  androidUseCustomKeystore: 1


하지만 비밀번호와 같은 정보는 별도로 저장되다보니
체크아웃을 새로 받을 때마다, keystore 세팅을 다시 해줘야했다.

 

 

| 현상

 

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':launcher:packageRelease'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > com.android.ide.common.signing.KeytoolException: Failed to read key creature from store "/Users/${USER}/.jenkins/workspace/${PROJECT_NAME}/Keystore/user.keystore": Keystore was tampered with, or password was incorrect

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings

ProjectSettings.asset 파일에는 androidUseCustomKeystore값은 1로 남아있는데,

alias나 비밀번호 같은 값이 날아가 버려서 위와 같은 에러가 발생한다.

 

 

| 해결

 

using UnityEditor;
using UnityEngine;

namespace Tools.Settings
{
    [FilePath("UserSettings/BuildConfigs.asset", FilePathAttribute.Location.ProjectFolder)]
    public class BuildConfigs : ScriptableSingleton<BuildConfigs>
    {
        public string __ks_pass;
        public string __ks_key_alias;
        public string __key_pass;

        public string KeyStorePassword => Base64.Decode(__ks_pass);
        public string KeyAlias => Base64.Decode(__ks_key_alias);
        public string KeyPass => Base64.Decode(__key_pass);

        public void Save()
        { 
            Save(true); 
        }
    }

    sealed class BuildConfigsProvider : SettingsProvider
    {
        public const string Url = "{url}/manage/configure";

        public BuildConfigsProvider()
          : base("Preferences/Build Configs", SettingsScope.User) 
        {

        }

        public override void OnGUI(string search)
        {
            var settings = BuildConfigs.instance;

            var __ks_pass = settings.KeyStorePassword;
            var __ks_key_alias = settings.KeyAlias;
            var __key_pass = settings.KeyPass;

            EditorGUI.BeginChangeCheck();

            __ks_pass = EditorGUILayout.PasswordField("--ks-pass", __ks_pass);
            __ks_key_alias = EditorGUILayout.PasswordField("--ks-key-alias", __ks_key_alias);
            __key_pass = EditorGUILayout.PasswordField("--key-pass", __key_pass);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Overview"))
            {
                Application.OpenURL(Url);
            }
            GUILayout.EndHorizontal();

            if (EditorGUI.EndChangeCheck())
            {
                settings.__ks_pass = Base64.Encode(__ks_pass);
                settings.__ks_key_alias = Base64.Encode(__ks_key_alias);
                settings.__key_pass = Base64.Encode(__key_pass);
                settings.Save();
            }
        }
    }

    static class BuildConfigsRegister
    {
        [SettingsProvider]
        public static SettingsProvider CreateCustomSettingsProvider()
          => new BuildConfigsProvider();
    }
}

CI 툴에서 파라미터로 전달해도 되지만, 

버전 관리 툴에서 관리되었으면 해서 UserSettings에 값을 저장할 수 있도록 하였다.

 

 

 

| 참고

 

 

Unity - Scripting API: SettingsProvider

In order to add new Project settings or preference pages, define a SettingsProvider. The SettingsProvider class provides the hooks to display any UI (using either IMGUI or UIElements to draw it). It also provides an API that allows you to specify keywords

docs.unity3d.com

 

반응형

+ Recent posts