Skip to content

Commit f1d5db3

Browse files
committed
chore(versionSynchronizer): add version code generation
1 parent bbcff3b commit f1d5db3

File tree

3 files changed

+82
-10
lines changed

3 files changed

+82
-10
lines changed

Assets/Editor/SyncBundleVersion.cs

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,104 @@
33
using UnityEditor.Build;
44
using UnityEditor.Build.Reporting;
55
using System.IO;
6+
using System.Text.RegularExpressions;
67

8+
/// <summary>
9+
/// Keeps Unity's version fields in sync with files generated by CI:
10+
/// - version.txt -> PlayerSettings.bundleVersion (maps to Android versionName)
11+
/// - versionCode.txt (optional) -> PlayerSettings.Android.bundleVersionCode
12+
///
13+
/// If versionCode.txt is missing, it will derive a versionCode from version.txt using:
14+
/// code = MAJOR*10000 + MINOR*100 + PATCH
15+
/// This ensures a monotonic integer for Google Play uploads.
16+
/// </summary>
717
public class SyncBundleVersionPreprocess : IPreprocessBuildWithReport
818
{
919
/// <summary>
10-
/// Determines the order in which build preprocessors are called.
11-
/// 0 means default/early execution.
20+
/// Determines the order in which build preprocessors are called. 0 means default/early execution.
1221
/// </summary>
1322
public int callbackOrder => 0;
1423

1524
/// <summary>
16-
/// Keeps Unity's internal application version (Application.version)
17-
/// in sync with CI/CD-managed versions.
25+
/// Keeps Unity's internal application version (Application.version) in sync with CI/CD-managed versions.
1826
/// </summary>
1927
public void OnPreprocessBuild(BuildReport report)
2028
{
21-
var versionPath = Path.Combine(Directory.GetCurrentDirectory(), "version.txt");
29+
var root = Directory.GetCurrentDirectory();
30+
31+
// 1) Sync human-readable version
32+
var versionPath = Path.Combine(root, "version.txt");
2233
if (File.Exists(versionPath))
2334
{
24-
// Read the file and trim extra whitespace/newlines
2535
var v = File.ReadAllText(versionPath).Trim();
2636

2737
// Update if the file is not empty and differs from current bundleVersion
28-
if (!string.IsNullOrEmpty(v) && UnityEditor.PlayerSettings.bundleVersion != v)
38+
if (!string.IsNullOrEmpty(v) && PlayerSettings.bundleVersion != v)
2939
{
30-
UnityEditor.PlayerSettings.bundleVersion = v; // Update Unity's app version
31-
40+
PlayerSettings.bundleVersion = v; // Update Unity's app version
3241
AssetDatabase.SaveAssets();
33-
UnityEngine.Debug.Log($"[Build] Synced PlayerSettings.bundleVersion -> {v}");
42+
UnityEngine.Debug.Log($"[Build] Synced bundleVersion -> {v}");
43+
}
44+
45+
// 2) Android versionCode: prefer explicit file; else derive from semver
46+
47+
48+
#if UNITY_ANDROID
49+
50+
// Local holder for the versionCode we want to apply to the Android build.
51+
int code; // Google Play requires this to be a monotonically increasing integer.
52+
var codePath = Path.Combine(root, "versionCode.txt");
53+
54+
// Preferred path: if versionCode.txt exists and contains a valid integer, use it as-is.
55+
if (File.Exists(codePath) && int.TryParse(File.ReadAllText(codePath).Trim(), out code))
56+
{
57+
SetAndroidVersionCodeIfDifferent(code);
58+
}
59+
else
60+
{
61+
// Fallback path: derive an integer versionCode from the semver in version.txt (string 'v').
62+
var m = Regex.Match(v, @"^(?<maj>\d+)\.(?<min>\d+)\.(?<pat>\d+)");
63+
if (m.Success)
64+
{
65+
// This scheme reserves two digits for MINOR and two for PATCH (00–99 each).
66+
// If you expect MINOR or PATCH to exceed 99, switch to a wider encoding
67+
// (e.g., MAJOR*1_000_000 + MINOR*1_000 + PATCH).
68+
int maj = int.Parse(m.Groups["maj"].Value);
69+
int min = int.Parse(m.Groups["min"].Value);
70+
int pat = int.Parse(m.Groups["pat"].Value);
71+
code = maj * 10000 + min * 100 + pat;
72+
SetAndroidVersionCodeIfDifferent(code);
73+
}
74+
else
75+
{
76+
// If version.txt doesn't match MAJOR.MINOR.PATCH, we can't derive a versionCode.
77+
// Build will still proceed with the current PlayerSettings.Android.bundleVersionCode.
78+
UnityEngine.Debug.LogWarning($"[Build] Could not parse semver from '{v}' to derive Android versionCode.");
79+
}
3480
}
81+
#endif
3582
}
3683
else
3784
{
3885
UnityEngine.Debug.LogWarning("[Build] version.txt not found; bundleVersion not changed.");
3986
}
4087
}
88+
89+
90+
#if UNITY_ANDROID && UNITY_EDITOR
91+
92+
/// <summary>
93+
/// Writes <see cref="PlayerSettings.Android.bundleVersionCode"/> if the value differ.
94+
/// </summary>
95+
private static void SetAndroidVersionCodeIfDifferent(int code)
96+
{
97+
if (PlayerSettings.Android.bundleVersionCode != code)
98+
{
99+
PlayerSettings.Android.bundleVersionCode = code; // Updates ProjectSettings/ProjectSettings.asset
100+
AssetDatabase.SaveAssets(); // Keeps the change
101+
UnityEngine.Debug.Log($"[Build] Synced Android bundleVersionCode -> {code}");
102+
}
103+
}
104+
#endif
41105
}
42106
#endif

Assets/versionCode.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Assets/versionCode.txt.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)