| 개요
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