Skip to content

Commit e81cb43

Browse files
authored
Merge pull request #8 from tsgcpp/feature/ci-update-localization-tables
feat: CI to update localization tables
2 parents ee275d5 + 60e6335 commit e81cb43

File tree

4 files changed

+189
-5
lines changed

4 files changed

+189
-5
lines changed

.github/.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: WIP Pull Localization from Google Sheets
2+
3+
on:
4+
workflow_dispatch: {}
5+
6+
env:
7+
KEY_JSON_PATH: 'SecretCache/UnityLocalizationExtension/service-account-key.json'
8+
BASE_BRANCH: ${{ github.ref_name }}
9+
HEAD_BRANCH: ${{ github.ref_name }}-update
10+
11+
jobs:
12+
pull-localization-tables:
13+
name: Pull Localization Tables
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v3
17+
with:
18+
lfs: true
19+
20+
- name: Generate Key
21+
shell: bash
22+
run: |
23+
mkdir -p $(dirname "${{ env.KEY_JSON_PATH }}")
24+
echo "${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY_JSON_BASE64 }}" | base64 --decode > "${{ env.KEY_JSON_PATH }}"
25+
26+
- name: Execute PullAllLocalizationTables
27+
uses: game-ci/unity-builder@v2
28+
env:
29+
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
30+
with:
31+
projectPath: ./
32+
unityVersion: 2021.3.6f1
33+
targetPlatform: Android
34+
buildMethod: Tsgcpp.Localization.Extension.Example.Editor.ExampleLocalizationSynchronizationMenu.PullAllLocalizationTablesFromTempKeyJson
35+
36+
- name: Delete Key
37+
if: always()
38+
run: |
39+
rm -f "${{ env.KEY_JSON_PATH }}"
40+
41+
- name: Git Commit String Tables
42+
id: commit
43+
shell: bash
44+
run: |
45+
set -eux
46+
47+
git checkout -b ${{ env.HEAD_BRANCH }}
48+
49+
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
50+
git config --local user.name "github-actions[bot]"
51+
52+
git reset
53+
git add --update "Assets/Example/StringTableCollection"
54+
DIFF_COUNT=$(git diff --staged --name-only | wc -l)
55+
56+
if [ "${DIFF_COUNT}" -le 0 ]
57+
then
58+
echo "::notice::Skipped the commit becuase no differences were found."
59+
exit 0
60+
fi
61+
62+
DATE=$(date '+%Y/%m/%d %H:%M')
63+
TITLE="Update StringCollectionTable (${DATE})"
64+
65+
git commit -m "${TITLE}"
66+
67+
echo "::set-output name=has_diff::true"
68+
echo "::set-output name=title::${TITLE}"
69+
70+
- name: Git Push ans PullRequest
71+
if: steps.commit.outputs.has_diff == 'true'
72+
shell: bash
73+
run: |
74+
REMOTE_SHA=$(git ls-remote --heads origin ${{ env.HEAD_BRANCH }})
75+
if [ -n "${REMOTE_SHA}" ]
76+
then
77+
git push origin :${{ env.HEAD_BRANCH }}
78+
echo "::notice::The remote branch (ref_name: ${{ env.HEAD_BRANCH }}, sha: ${REMOTE_SHA})"
79+
fi
80+
81+
git push origin ${{ env.HEAD_BRANCH }}
82+
83+
sleep 2
84+
85+
PR_URL=$(gh pr create \
86+
--base "${{ env.BASE_BRANCH }}" \
87+
--head "${{ env.HEAD_BRANCH }}" \
88+
--title "${{ steps.commit.outputs.title }}" \
89+
--body "" \
90+
)
91+
92+
echo "::notice::${PR_URL} was issued."
93+
94+
env:
95+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
96+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
97+
98+
- name: Notice
99+
run: |
100+
echo "This is a notification phase"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,6 @@ crashlytics-build.properties
7272
# Temporary auto-generated Android Assets
7373
/[Aa]ssets/[Ss]treamingAssets/aa.meta
7474
/[Aa]ssets/[Ss]treamingAssets/aa/*
75+
76+
# Temp Cache
77+
/[Ss]ecret[Cc]ache/

Assets/Example/Editor/ExampleLocalizationSynchronizationMenu.cs

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using UnityEngine;
33
using UnityEditor;
44
using Tsgcpp.Localization.Extension.Editor.Google;
5+
using System.IO;
56

67
namespace Tsgcpp.Localization.Extension.Example.Editor
78
{
@@ -12,8 +13,6 @@ public static class ExampleLocalizationSynchronizationMenu
1213
/// <summary>
1314
/// Environment variable name for Google Sheets API key (Json format).
1415
/// </summary>
15-
private const string EnvironmentGoogleServiceAccountKey = "UNITY_LOCALIZATION_GOOGLE_SERVICE_ACCOUNT_KEY";
16-
1716
[MenuItem("Localization Extension Example/Pull All Localization Tables", false, priority = 1)]
1817
internal static void PullAllLocalizationTablesMenu()
1918
{
@@ -38,6 +37,21 @@ internal static void PullAllLocalizationTablesWithGoogleServiceAccount()
3837
bundle.PullAllLocales(provider);
3938
}
4039

40+
/// <summary>
41+
/// Pull all StringTables in StringTableCollectionBundle from Google Spreadsheet.
42+
/// </summary>
43+
/// <remarks>
44+
/// This method can also be used in CI.
45+
/// This is for environments that cannot use environment variables.
46+
/// FYI: GameCI cannot use additional environemnt variables.
47+
/// </remarks>
48+
internal static void PullAllLocalizationTablesFromTempKeyJson()
49+
{
50+
var bundle = Bundle;
51+
var provider = GetServiceAccountSheetsServiceProviderFromKeyJson(bundle);
52+
bundle.PullAllLocales(provider);
53+
}
54+
4155
#endregion
4256

4357
#region Push
@@ -66,15 +80,72 @@ internal static void PushAllLocalizationTablesWithGoogleServiceAccount()
6680
bundle.PushAllLocales(provider);
6781
}
6882

83+
/// <summary>
84+
/// Push all StringTables in StringTableCollectionBundle to Google Spreadsheet.
85+
/// </summary>
86+
/// <remarks>
87+
/// This method can also be used in CI.
88+
/// This is for environments that cannot use environment variables.
89+
/// FYI: GameCI cannot use additional environemnt variables.
90+
/// </remarks>
91+
internal static void PushAllLocalizationTablesWithGoogleServiceAccountFromTempKeyJson()
92+
{
93+
var bundle = Bundle;
94+
var provider = GetServiceAccountSheetsServiceProviderFromKeyJson(bundle);
95+
bundle.PushAllLocales(provider);
96+
}
97+
6998
#endregion
7099

100+
#region Service Account Key from Environment Variable
101+
102+
internal static ServiceAccountSheetsServiceProvider GetServiceAccountSheetsServiceProvider(
103+
StringTableCollectionBundle bundle)
104+
{
105+
const string EnvironmentGoogleServiceAccountKey = "UNITY_LOCALIZATION_GOOGLE_SERVICE_ACCOUNT_KEY";
106+
return GetServiceAccountSheetsServiceProvider(bundle, EnvironmentGoogleServiceAccountKey);
107+
}
108+
71109
internal static ServiceAccountSheetsServiceProvider GetServiceAccountSheetsServiceProvider(
110+
StringTableCollectionBundle bundle,
111+
string keyEnvironmentVariableName)
112+
{
113+
var serviceAccountKeyJson = Environment.GetEnvironmentVariable(keyEnvironmentVariableName);
114+
if (string.IsNullOrEmpty(serviceAccountKeyJson))
115+
{
116+
throw new InvalidOperationException($"Environment variable \"{keyEnvironmentVariableName}\" is not set.");
117+
}
118+
119+
var provider = new ServiceAccountSheetsServiceProvider(
120+
serviceAccountKeyJson: serviceAccountKeyJson,
121+
applicationName: bundle.SheetsServiceProvider.ApplicationName);
122+
return provider;
123+
}
124+
125+
#endregion
126+
127+
#region Service Account Key from Json File
128+
129+
internal static ServiceAccountSheetsServiceProvider GetServiceAccountSheetsServiceProviderFromKeyJson(
72130
StringTableCollectionBundle bundle)
73131
{
74-
var serviceAccountKeyJson = Environment.GetEnvironmentVariable(EnvironmentGoogleServiceAccountKey);
132+
const string JsonKeyPath = "SecretCache/UnityLocalizationExtension/service-account-key.json";
133+
return GetServiceAccountSheetsServiceProviderFromKeyJson(bundle, JsonKeyPath);
134+
}
135+
136+
internal static ServiceAccountSheetsServiceProvider GetServiceAccountSheetsServiceProviderFromKeyJson(
137+
StringTableCollectionBundle bundle,
138+
string keyJsonPath)
139+
{
140+
if (!File.Exists(keyJsonPath))
141+
{
142+
throw new InvalidOperationException($"File \"{keyJsonPath}\" is not found.");
143+
}
144+
145+
string serviceAccountKeyJson = File.ReadAllText(keyJsonPath);
75146
if (string.IsNullOrEmpty(serviceAccountKeyJson))
76147
{
77-
throw new InvalidOperationException($"Environment variable \"{EnvironmentGoogleServiceAccountKey}\" is not set.");
148+
throw new InvalidOperationException($"File \"{keyJsonPath}\" is empty.");
78149
}
79150

80151
var provider = new ServiceAccountSheetsServiceProvider(
@@ -83,6 +154,8 @@ internal static ServiceAccountSheetsServiceProvider GetServiceAccountSheetsServi
83154
return provider;
84155
}
85156

157+
#endregion
158+
86159
private const string BundlePath = "Assets/Example/StringTableCollectionBundle/StringTableCollectionBundle.asset";
87160

88161
public static StringTableCollectionBundle Bundle => GetStringTableCollectionBundle(BundlePath);
@@ -97,6 +170,5 @@ private static StringTableCollectionBundle GetStringTableCollectionBundle(string
97170

98171
return bundle;
99172
}
100-
101173
}
102174
}

0 commit comments

Comments
 (0)