-
Notifications
You must be signed in to change notification settings - Fork 455
/
translations_auto_pr.js
215 lines (177 loc) · 8.51 KB
/
translations_auto_pr.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
'use strict'
const fs = require("fs-extra");
const cp = require("child_process");
const Octokit = require('@octokit/rest')
const path = require('path');
const parseGitConfig = require('parse-git-config');
const branchName = 'localization';
const mergeTo = 'main';
const commitComment = 'Localization - Translated Strings';
const pullRequestTitle = '[Auto] Localization - Translated Strings';
let repoOwner = process.argv[2];
let repoName = process.argv[3];
let authUser = process.argv[4];
let authToken = process.argv[5];
let userFullName = process.argv[6];
let userEmail = process.argv[7];
let locRootPath = process.argv[8];
let locSubPath = process.argv[9];
if (!repoOwner || !repoName || !authUser || !authToken || !userFullName || !userEmail || !locRootPath || !locSubPath) {
console.error(`ERROR: Usage: ${path.parse(process.argv[0]).base} ${path.parse(process.argv[1]).base} repo_owner repo_name auth_token user_full_name user_email loc_root_path loc_sub_path`);
console.error(` repo_owner - The owner of the repo on GitHub. i.e. microsoft`);
console.error(` repo_name - The name of the repo on GitHub. i.e. vscode-cpptools`);
console.error(` auth_user - User account wiith permission to post a pull request against the GitHub repo.`);
console.error(` auth_token - A PAT associated with auth_user.`);
console.error(` user_full_name - A full name to associate with a git commit. (This is replaced by the PR account if commit is squashed.)`);
console.error(` user_email - An email to associate with a git commit. (This is replaced by the PR account if commit is squashed.)`);
console.error(` loc_root_path - The path to the folder with language-specific directories (containing localized xlf files).`);
console.error(` loc_sub_path - A sub-path after the language-specific directory, where the xlf to import is located. This should not include the name of the xlf file to import.)`);
return;
}
console.log(`repoOwner=${repoOwner}`);
console.log(`repoName=${repoName}`);
console.log(`authUser=${authUser}`);
console.log(`userFullName=${userFullName}`);
console.log(`userEmail=${userEmail}`);
console.log(`locRootPath=${locRootPath}`);
console.log(`locSubPath=${locSubPath}`);
function hasBranch(branchName) {
console.log(`Checking for existence of branch "${branchName}" (git branch --list ${branchName})`);
let output = cp.execSync(`git branch --list ${branchName}`);
let lines = output.toString().split("\n");
let found = false;
lines.forEach(line => {
found = found || (line === ` ${branchName}`);
});
return found;
}
function hasAnyChanges() {
console.log("Checking if any files have changed (git status --porcelain)");
let output = cp.execSync('git status --porcelain');
let lines = output.toString().split("\n");
let anyChanges = false;
lines.forEach(line => {
if (line != '') {
console.log("Change detected: " + line);
anyChanges = true;
}
});
return anyChanges;
}
// When invoked on build server, we should already be in a repo freshly synced to the mergeTo branch
if (hasAnyChanges()) {
console.log(`Changes already present in this repo! This script is intended to be run against a freshly synced ${mergeTo} branch!`);
return;
}
function sleep(ms) {
var unixtime_ms = new Date().getTime();
while(new Date().getTime() < unixtime_ms + ms) {}
}
console.log("This script is potentially DESTRUCTIVE! Cancel now, or it will proceed in 10 seconds.");
sleep(10000);
let directories = [ "cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-Hans", "zh-Hant" ];
directories.forEach(languageId => {
let sourcePath = `${locRootPath}\\${languageId}\\${locSubPath}\\${repoName}.${languageId}.xlf`;
let destinationPath = `./vscode-translations-import/${languageId}/vscode-extensions/${repoName}.xlf`;
console.log(`Copying "${sourcePath}" to "${destinationPath}"`);
fs.copySync(sourcePath, destinationPath);
});
console.log("Import translations into i18n directory");
cp.execSync("npm run translations-import");
if (!hasAnyChanges()) {
console.log("No changes detected");
return;
}
console.log("Changes detected");
console.log(`Ensure main ref is up to date locally (git fetch)`);
cp.execSync('git fetch');
// Remove old localization branch, if any
if (hasBranch("localization")) {
console.log(`Remove old localization branch, if any (git branch -D localization)`);
cp.execSync('git branch -D localization');
}
// Check out local branch
console.log(`Creating local branch for changes (git checkout -b ${branchName})`);
cp.execSync('git checkout -b localization');
// Add changed files.
console.log("Adding changed file (git add .)");
cp.execSync('git add .');
// git add may have resolves CR/LF's and there may not be anything to commit
if (!hasAnyChanges()) {
console.log("No changes detected. The only changes must have been due to CR/LF's, and have been corrected.");
return;
}
// Set up user and permissions
// Save existing user name and email, in case already set.
var existingUserName;
var existingUserEmail;
var gitConfigPath = path.resolve(process.cwd(), './.git/config');
var config = parseGitConfig.sync({ path: gitConfigPath });
if (typeof config === 'object' && config.hasOwnProperty('user')) {
existingUserName = config.user.name;
existingUserEmail = config.user.email;
}
if (existingUserName === undefined) {
console.log(`Existing user name: undefined`);
} else {
console.log(`Existing user name: "${existingUserName}"`);
cp.execSync(`git config --local --unset user.name`);
}
if (existingUserEmail === undefined) {
console.log(`Existing user email: undefined`);
} else {
console.log(`Existing user email: "${existingUserEmail}"`);
cp.execSync(`git config --local --unset user.email`);
}
console.log(`Setting local user name to: "${userFullName}"`);
cp.execSync(`git config --local user.name "${userFullName}"`);
console.log(`Setting local user email to: "${userEmail}"`);
cp.execSync(`git config --local user.email "${userEmail}"`);
console.log(`Configuring git with permission to push and to create pull requests (git remote remove origin && git remote add origin https://${authUser}:${authToken}@github.com/${repoOwner}/${repoName}.git`);
cp.execSync('git remote remove origin');
cp.execSync(`git remote add origin https://${authUser}:${authToken}@github.com/${repoOwner}/${repoName}.git`);
// Commit changed files.
console.log(`Commiting changes (git commit -m "${commitComment}")`);
cp.execSync(`git commit -m "${commitComment}"`);
if (existingUserName === undefined) {
console.log(`Restoring original user name: undefined`);
cp.execSync(`git config --local --unset user.name`);
} else {
console.log(`Restoring original user name: "${existingUserName}"`);
cp.execSync(`git config --local user.name "${existingUserName}"`);
}
if (existingUserEmail === undefined) {
console.log(`Restoring original user email: undefined`);
cp.execSync(`git config --local --unset user.email`);
} else {
console.log(`Restoring original user email: "${existingUserEmail}"`);
cp.execSync(`git config --local user.email "${existingUserEmail}"`);
}
console.log(`pushing to remove branch (git push -f origin ${branchName})`);
cp.execSync(`git push -f origin ${branchName}`);
console.log("Checking if there is already a pull request...");
const octokit = new Octokit.Octokit({auth: authToken});
octokit.pulls.list({ owner: repoOwner, repo: repoName }).then(({data}) => {
let alreadyHasPullRequest = false;
if (data) {
data.forEach((pr) => {
alreadyHasPullRequest = alreadyHasPullRequest || (pr.title === pullRequestTitle);
});
}
// If not already present, create a PR against our remote branch.
if (!alreadyHasPullRequest) {
console.log("There is not already a pull request. Creating one.");
octokit.pulls.create({ body:"", owner: repoOwner, repo: repoName, title: pullRequestTitle, head: branchName, base: mergeTo });
} else {
console.log("There is already a pull request.");
}
console.log(`Restoring default git permissions`);
cp.execSync('git remote remove origin');
cp.execSync(`git remote add origin https://github.com/${repoOwner}/${repoName}.git`);
console.log(`Run 'git fetch' against updated remote`);
cp.execSync('git fetch');
console.log(`Switching back to ${mergeTo} (git checkout ${mergeTo})`);
cp.execSync(`git checkout ${mergeTo}`);
console.log(`Remove localization branch (git branch -D localization)`);
cp.execSync('git branch -D localization');
});