ota-manager 1.0.6 ā 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/flatten-dist.cjs +6 -3
- package/lib/ota-build.cjs +505 -280
- package/lib/ota-deploy.js +84 -4
- package/lib/ota-main.js +243 -214
- package/lib/ota-rollback.js +130 -0
- package/lib/ota-version.js +34 -9
- package/package.json +1 -1
package/lib/ota-deploy.js
CHANGED
|
@@ -160,7 +160,7 @@ async function deployOTA() {
|
|
|
160
160
|
execSync('npm run build', { stdio: 'inherit', cwd: rootDir });
|
|
161
161
|
|
|
162
162
|
if (fs.existsSync(FLATTEN_SCRIPT)) {
|
|
163
|
-
console.log('š Running
|
|
163
|
+
console.log('š Running Absolute Path Normalization...');
|
|
164
164
|
execSync(`node "${FLATTEN_SCRIPT}"`, { stdio: 'inherit', cwd: rootDir });
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -192,7 +192,9 @@ async function deployOTA() {
|
|
|
192
192
|
console.log('š Changes detected! Auto-incrementing from remote manifest...');
|
|
193
193
|
const parts = previousVersion.split('.');
|
|
194
194
|
const lastIdx = parts.length - 1;
|
|
195
|
-
|
|
195
|
+
const oldPart = parts[lastIdx];
|
|
196
|
+
const oldLen = oldPart.length;
|
|
197
|
+
parts[lastIdx] = (parseInt(oldPart) + 1).toString().padStart(oldLen, '0');
|
|
196
198
|
nextVersion = parts.join('.');
|
|
197
199
|
console.log(`š Auto-increment: ${previousVersion} -> ${nextVersion}`);
|
|
198
200
|
}
|
|
@@ -221,12 +223,90 @@ async function deployOTA() {
|
|
|
221
223
|
|
|
222
224
|
console.log(`š Updating .env to version ${nextVersion} (Android & iOS) and setting OTA target...`);
|
|
223
225
|
fs.writeFileSync(ENV_PATH, updatedEnv);
|
|
226
|
+
|
|
227
|
+
const envLivePath = path.join(rootDir, '.env-live');
|
|
228
|
+
const envTrainingPath = path.join(rootDir, '.env-training');
|
|
229
|
+
if (argChannel === 'live' && fs.existsSync(envLivePath)) {
|
|
230
|
+
let liveEnv = fs.readFileSync(envLivePath, 'utf-8');
|
|
231
|
+
liveEnv = liveEnv.replace(/PUBLIC_APP_VERSION=.*/, `PUBLIC_APP_VERSION=${nextVersion}`);
|
|
232
|
+
if (liveEnv.includes('PUBLIC_OTA_UPDATE_URL=')) {
|
|
233
|
+
liveEnv = liveEnv.replace(/PUBLIC_OTA_UPDATE_URL=.*/, `PUBLIC_OTA_UPDATE_URL=${activeOtaUrl}`);
|
|
234
|
+
} else {
|
|
235
|
+
liveEnv += `\nPUBLIC_OTA_UPDATE_URL=${activeOtaUrl}`;
|
|
236
|
+
}
|
|
237
|
+
fs.writeFileSync(envLivePath, liveEnv);
|
|
238
|
+
console.log(`š Updated .env-live to version ${nextVersion}`);
|
|
239
|
+
}
|
|
240
|
+
if (argChannel === 'training' && fs.existsSync(envTrainingPath)) {
|
|
241
|
+
let trainingEnv = fs.readFileSync(envTrainingPath, 'utf-8');
|
|
242
|
+
trainingEnv = trainingEnv.replace(/PUBLIC_APP_VERSION=.*/, `PUBLIC_APP_VERSION=${nextVersion}`);
|
|
243
|
+
if (trainingEnv.includes('PUBLIC_OTA_UPDATE_URL=')) {
|
|
244
|
+
trainingEnv = trainingEnv.replace(/PUBLIC_OTA_UPDATE_URL=.*/, `PUBLIC_OTA_UPDATE_URL=${activeOtaUrl}`);
|
|
245
|
+
} else {
|
|
246
|
+
trainingEnv += `\nPUBLIC_OTA_UPDATE_URL=${activeOtaUrl}`;
|
|
247
|
+
}
|
|
248
|
+
fs.writeFileSync(envTrainingPath, trainingEnv);
|
|
249
|
+
console.log(`š Updated .env-training to version ${nextVersion}`);
|
|
250
|
+
}
|
|
224
251
|
|
|
252
|
+
// Sync Native Android & iOS Versions
|
|
253
|
+
try {
|
|
254
|
+
const partsStr = nextVersion.split('.');
|
|
255
|
+
let majorStr = partsStr[0] || '0';
|
|
256
|
+
let minorStr = partsStr[1] || '0';
|
|
257
|
+
let patchStr = partsStr[2] || '00';
|
|
258
|
+
if (patchStr.length === 1) patchStr = '0' + patchStr;
|
|
259
|
+
const versionCodeNum = parseInt(`${majorStr}${minorStr}${patchStr}`, 10) || 1;
|
|
260
|
+
|
|
261
|
+
const buildGradlePath = path.join(rootDir, 'android', 'app', 'build.gradle');
|
|
262
|
+
if (fs.existsSync(buildGradlePath)) {
|
|
263
|
+
let bgContent = fs.readFileSync(buildGradlePath, 'utf8');
|
|
264
|
+
bgContent = bgContent.replace(/versionCode\s+\d+/, `versionCode ${versionCodeNum}`);
|
|
265
|
+
bgContent = bgContent.replace(/versionName\s+".*?"/, `versionName "${nextVersion}"`);
|
|
266
|
+
fs.writeFileSync(buildGradlePath, bgContent);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const pbxprojPath = path.join(rootDir, 'ios', 'App', 'App.xcodeproj', 'project.pbxproj');
|
|
270
|
+
if (fs.existsSync(pbxprojPath)) {
|
|
271
|
+
let pbxContent = fs.readFileSync(pbxprojPath, 'utf8');
|
|
272
|
+
pbxContent = pbxContent.replace(/CURRENT_PROJECT_VERSION = \d+;/g, `CURRENT_PROJECT_VERSION = ${versionCodeNum};`);
|
|
273
|
+
pbxContent = pbxContent.replace(/MARKETING_VERSION = .*?;/g, `MARKETING_VERSION = ${nextVersion};`);
|
|
274
|
+
fs.writeFileSync(pbxprojPath, pbxContent);
|
|
275
|
+
}
|
|
276
|
+
console.log(`ā
Native Android & iOS versions synchronized (versionCode: ${versionCodeNum}).`);
|
|
277
|
+
} catch (err) {
|
|
278
|
+
console.error('ā ļø Warning: Failed to sync native versions:', err.message);
|
|
279
|
+
}
|
|
280
|
+
|
|
225
281
|
if (fs.existsSync(MAIN_MANIFEST_PATH)) {
|
|
226
282
|
const manifest = JSON.parse(fs.readFileSync(MAIN_MANIFEST_PATH, 'utf8'));
|
|
227
283
|
manifest.version = nextVersion;
|
|
228
284
|
fs.writeFileSync(MAIN_MANIFEST_PATH, JSON.stringify(manifest, null, 2));
|
|
229
285
|
}
|
|
286
|
+
const pkgJsonPath = path.join(rootDir, 'package.json');
|
|
287
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
288
|
+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
289
|
+
pkgJson.version = nextVersion;
|
|
290
|
+
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
console.log('šļø Rebuilding Astro to bake new version string into JS bundle...');
|
|
294
|
+
hideApi();
|
|
295
|
+
try {
|
|
296
|
+
execSync('npm run build', { stdio: 'inherit', cwd: rootDir });
|
|
297
|
+
|
|
298
|
+
if (fs.existsSync(FLATTEN_SCRIPT)) {
|
|
299
|
+
console.log('š Running Absolute Path Normalization...');
|
|
300
|
+
execSync(`node "${FLATTEN_SCRIPT}"`, { stdio: 'inherit', cwd: rootDir });
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (fs.existsSync(VERIFY_SCRIPT)) {
|
|
304
|
+
console.log('š Running Pre-Flight Verification...');
|
|
305
|
+
execSync(`node "${VERIFY_SCRIPT}"`, { stdio: 'inherit', cwd: rootDir });
|
|
306
|
+
}
|
|
307
|
+
} finally {
|
|
308
|
+
showApi();
|
|
309
|
+
}
|
|
230
310
|
|
|
231
311
|
console.log('š”ļø Size Guardian: Checking dist/ folder size...');
|
|
232
312
|
const distSizeBytes = getDirSize(DIST_DIR);
|
|
@@ -237,7 +317,7 @@ async function deployOTA() {
|
|
|
237
317
|
throw new Error(`CRITICAL SIZE VIOLATION: Folder dist/ has bloated to ${distSizeMB.toFixed(2)} MB! Limit is ${MAX_OTA_SIZE_MB} MB. Packaging aborted to prevent ZIP BOMB!`);
|
|
238
318
|
}
|
|
239
319
|
|
|
240
|
-
const otaName =
|
|
320
|
+
const otaName = `${nextVersion.replace(/\./g, '_')}.zip`;
|
|
241
321
|
const otaPath = path.join(rootDir, otaName);
|
|
242
322
|
|
|
243
323
|
const isWindows = process.platform === 'win32';
|
|
@@ -306,7 +386,7 @@ async function deployToRemote(otaPath, otaName, version, channel, branch, buildH
|
|
|
306
386
|
fs.writeFileSync(flatManifestPath, JSON.stringify(manifest[channel], null, 2));
|
|
307
387
|
|
|
308
388
|
execSync(`git add .`, { cwd: OTA_RELEASES_DIR });
|
|
309
|
-
execSync(`git commit -m "release:
|
|
389
|
+
execSync(`git commit -m "release: ${version} for ${channel}"`, { cwd: OTA_RELEASES_DIR });
|
|
310
390
|
execSync(`git push origin ${branch}`, { cwd: OTA_RELEASES_DIR });
|
|
311
391
|
|
|
312
392
|
if (fs.existsSync(otaPath)) fs.unlinkSync(otaPath);
|
package/lib/ota-main.js
CHANGED
|
@@ -1,214 +1,243 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import OTA_CONFIG from './ota-config.js';
|
|
6
|
-
import { listConfigs, useConfig, registerConfig, testConnection } from './ota-manager.js';
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
const rootDir = process.cwd();
|
|
11
|
-
|
|
12
|
-
const command = process.argv[2];
|
|
13
|
-
const subArg = process.argv[3];
|
|
14
|
-
const versionArg = process.argv[4];
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const
|
|
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
|
-
case '
|
|
110
|
-
case '
|
|
111
|
-
|
|
112
|
-
process.exit(0);
|
|
113
|
-
break;
|
|
114
|
-
|
|
115
|
-
case '
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
case '
|
|
133
|
-
|
|
134
|
-
process.exit(0);
|
|
135
|
-
break;
|
|
136
|
-
|
|
137
|
-
case '
|
|
138
|
-
|
|
139
|
-
execSync(`node "${scripts.
|
|
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
|
-
console.log(
|
|
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
|
-
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import OTA_CONFIG from './ota-config.js';
|
|
6
|
+
import { listConfigs, useConfig, registerConfig, testConnection } from './ota-manager.js';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const rootDir = process.cwd();
|
|
11
|
+
|
|
12
|
+
const command = process.argv[2];
|
|
13
|
+
const subArg = process.argv[3];
|
|
14
|
+
const versionArg = process.argv[4];
|
|
15
|
+
|
|
16
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
18
|
+
const TOOL_VERSION = pkg.version;
|
|
19
|
+
|
|
20
|
+
const scripts = {
|
|
21
|
+
version: path.join(__dirname, 'ota-version.js'),
|
|
22
|
+
deploy: path.join(__dirname, 'ota-deploy.js'),
|
|
23
|
+
verify: path.join(__dirname, 'verify-dist.cjs'),
|
|
24
|
+
security: path.join(__dirname, 'ota-security.js'),
|
|
25
|
+
build: path.join(__dirname, 'ota-build.cjs'),
|
|
26
|
+
rollback: path.join(__dirname, 'ota-rollback.js'),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function showHelp() {
|
|
30
|
+
console.log(`
|
|
31
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
32
|
+
ā OTA MANAGER ā
|
|
33
|
+
ā Version ${TOOL_VERSION} ā
|
|
34
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
35
|
+
|
|
36
|
+
Usage: npx ota-manager <command> [sub-command] [version]
|
|
37
|
+
|
|
38
|
+
Management Commands:
|
|
39
|
+
list : Show all registered infrastructures.
|
|
40
|
+
use <id> : Set default infrastructure (e.g., use gitlab).
|
|
41
|
+
register <id> : Register or update infrastructure (e.g., register s3).
|
|
42
|
+
verify : Verify active infrastructure connectivity.
|
|
43
|
+
audit : Audit public token for security leaks.
|
|
44
|
+
test : Run E2E simulation (Push & Read).
|
|
45
|
+
|
|
46
|
+
Operational Commands:
|
|
47
|
+
status : Check local vs remote version.
|
|
48
|
+
deploy training : Deploy update to TRAINING channel.
|
|
49
|
+
deploy live : Deploy update to LIVE channel.
|
|
50
|
+
rollback <v> [ch] : Rollback / Downgrade ke versi lama (e.g., rollback 2.0.00 training).
|
|
51
|
+
|
|
52
|
+
Native Build Commands:
|
|
53
|
+
build android : Build Android APK Debug (default).
|
|
54
|
+
build android release : Build Android APK Release (assembleRelease).
|
|
55
|
+
build android bundle : Build Android App Bundle (.aab) siap rilis Play Store.
|
|
56
|
+
build ios : Trigger iOS GitHub Actions build & sync branding (Debug/Sideloading).
|
|
57
|
+
build ios release : Trigger iOS App Store Release signed build & sync branding.
|
|
58
|
+
* Gunakan flag 'no', 'norev', 'nover', '-no', atau '-nv' di akhir perintah untuk mencegah kenaikan versi.
|
|
59
|
+
|
|
60
|
+
Active Infrastructure:
|
|
61
|
+
Strategy : ${OTA_CONFIG.strategy.toUpperCase()}
|
|
62
|
+
Repo : ${OTA_CONFIG[OTA_CONFIG.strategy]?.repo || 'Not Configured'}
|
|
63
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
import readline from 'readline';
|
|
68
|
+
|
|
69
|
+
function confirm(message) {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const rl = readline.createInterface({
|
|
72
|
+
input: process.stdin,
|
|
73
|
+
output: process.stdout
|
|
74
|
+
});
|
|
75
|
+
rl.question(`\nā ļø ${message} [y/N]: `, (answer) => {
|
|
76
|
+
rl.close();
|
|
77
|
+
resolve(answer.toLowerCase() === 'y');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function run() {
|
|
83
|
+
try {
|
|
84
|
+
switch (command) {
|
|
85
|
+
case 'list':
|
|
86
|
+
await listConfigs();
|
|
87
|
+
process.exit(0);
|
|
88
|
+
break;
|
|
89
|
+
|
|
90
|
+
case 'use':
|
|
91
|
+
if (!subArg) {
|
|
92
|
+
console.log('ā Error: Please specify the infrastructure ID (e.g., use gitlab).');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
await useConfig(subArg);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
break;
|
|
98
|
+
|
|
99
|
+
case 'register':
|
|
100
|
+
if (!subArg) {
|
|
101
|
+
console.log('ā Error: Please specify the ID (e.g., register gitlab).');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
await registerConfig(subArg);
|
|
105
|
+
process.exit(0);
|
|
106
|
+
break;
|
|
107
|
+
|
|
108
|
+
case 'help':
|
|
109
|
+
case '-h':
|
|
110
|
+
case '--help':
|
|
111
|
+
showHelp();
|
|
112
|
+
process.exit(0);
|
|
113
|
+
break;
|
|
114
|
+
|
|
115
|
+
case '-v':
|
|
116
|
+
case '--version':
|
|
117
|
+
console.log(`OTA Manager v${TOOL_VERSION}`);
|
|
118
|
+
process.exit(0);
|
|
119
|
+
break;
|
|
120
|
+
|
|
121
|
+
case 'status':
|
|
122
|
+
case 'version':
|
|
123
|
+
execSync(`node "${scripts.version}"`, { stdio: 'inherit' });
|
|
124
|
+
process.exit(0);
|
|
125
|
+
break;
|
|
126
|
+
|
|
127
|
+
case 'verify':
|
|
128
|
+
execSync(`node "${scripts.verify}"`, { stdio: 'inherit' });
|
|
129
|
+
process.exit(0);
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
case 'test':
|
|
133
|
+
await testConnection();
|
|
134
|
+
process.exit(0);
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
case 'build':
|
|
138
|
+
const allArgs = process.argv.slice(3).join(' ');
|
|
139
|
+
execSync(`node "${scripts.build}" ${allArgs}`, { stdio: 'inherit' });
|
|
140
|
+
process.exit(0);
|
|
141
|
+
break;
|
|
142
|
+
|
|
143
|
+
case 'audit':
|
|
144
|
+
case 'security-check':
|
|
145
|
+
case 'security':
|
|
146
|
+
execSync(`node "${scripts.security}"`, { stdio: 'inherit' });
|
|
147
|
+
process.exit(0);
|
|
148
|
+
break;
|
|
149
|
+
|
|
150
|
+
case 'rollback':
|
|
151
|
+
case 'downgrade':
|
|
152
|
+
case 'set-version':
|
|
153
|
+
if (!subArg) {
|
|
154
|
+
console.log('ā Error: Mohon tentukan versi tujuan (e.g., npx ota-manager rollback 0.2.0.11 training).');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
const rbChannel = versionArg || 'training';
|
|
158
|
+
if (await confirm(`ARE YOU SURE you want to rollback ${rbChannel.toUpperCase()} to version ${subArg}?`)) {
|
|
159
|
+
execSync(`node "${scripts.rollback}" ${subArg} ${rbChannel}`, { stdio: 'inherit' });
|
|
160
|
+
} else {
|
|
161
|
+
console.log('ā Rollback cancelled.');
|
|
162
|
+
}
|
|
163
|
+
process.exit(0);
|
|
164
|
+
break;
|
|
165
|
+
|
|
166
|
+
case 'training':
|
|
167
|
+
execSync(`node "${scripts.version}"`, { stdio: 'inherit' });
|
|
168
|
+
execSync(`node "${scripts.verify}"`, { stdio: 'inherit' });
|
|
169
|
+
|
|
170
|
+
console.log(`\nš DEPLOYMENT PLAN [TRAINING]`);
|
|
171
|
+
console.log(`š¹ Infra : ${OTA_CONFIG.strategy.toUpperCase()}`);
|
|
172
|
+
console.log(`š¹ Action : Build & Push to Training Channel`);
|
|
173
|
+
|
|
174
|
+
if (await confirm('Proceed with TRAINING deployment?')) {
|
|
175
|
+
execSync(`node "${scripts.deploy}" training ${subArg || ''}`, { stdio: 'inherit' });
|
|
176
|
+
} else {
|
|
177
|
+
console.log('ā Deployment cancelled.');
|
|
178
|
+
}
|
|
179
|
+
process.exit(0);
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
case 'live':
|
|
183
|
+
execSync(`node "${scripts.version}"`, { stdio: 'inherit' });
|
|
184
|
+
execSync(`node "${scripts.verify}"`, { stdio: 'inherit' });
|
|
185
|
+
|
|
186
|
+
console.log(`\nšØ WARNING: DEPLOYMENT KE LIVE [PRODUCTION]`);
|
|
187
|
+
console.log(`š¹ Infra : ${OTA_CONFIG.strategy.toUpperCase()}`);
|
|
188
|
+
console.log(`š¹ Action : Build & Push to LIVE Channel`);
|
|
189
|
+
|
|
190
|
+
if (await confirm('ARE YOU SURE you want to deploy to LIVE?')) {
|
|
191
|
+
execSync(`node "${scripts.deploy}" live ${subArg || ''}`, { stdio: 'inherit' });
|
|
192
|
+
} else {
|
|
193
|
+
console.log('ā LIVE Deployment cancelled.');
|
|
194
|
+
}
|
|
195
|
+
process.exit(0);
|
|
196
|
+
break;
|
|
197
|
+
|
|
198
|
+
case '-d':
|
|
199
|
+
case 'deploy':
|
|
200
|
+
if (!subArg) {
|
|
201
|
+
console.log('ā Error: Mohon tentukan channel (e.g., deploy training atau deploy live).');
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const channel = subArg.toLowerCase();
|
|
205
|
+
if (channel !== 'training' && channel !== 'live') {
|
|
206
|
+
console.log(`ā Error: Channel "${channel}" tidak dikenal. Gunakan 'training' atau 'live'.`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
execSync(`node "${scripts.version}"`, { stdio: 'inherit' });
|
|
211
|
+
execSync(`node "${scripts.verify}"`, { stdio: 'inherit' });
|
|
212
|
+
|
|
213
|
+
if (channel === 'training') {
|
|
214
|
+
console.log(`\nš DEPLOYMENT PLAN [TRAINING]`);
|
|
215
|
+
console.log(`š¹ Infra : ${OTA_CONFIG.strategy.toUpperCase()}`);
|
|
216
|
+
console.log(`š¹ Action : Build & Push to Training Channel`);
|
|
217
|
+
} else {
|
|
218
|
+
console.log(`\nšØ WARNING: DEPLOYMENT KE LIVE [PRODUCTION]`);
|
|
219
|
+
console.log(`š¹ Infra : ${OTA_CONFIG.strategy.toUpperCase()}`);
|
|
220
|
+
console.log(`š¹ Action : Build & Push to LIVE Channel`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (await confirm(`Proceed with ${channel.toUpperCase()} deployment?`)) {
|
|
224
|
+
execSync(`node "${scripts.deploy}" ${channel} ${versionArg || ''}`, { stdio: 'inherit' });
|
|
225
|
+
} else {
|
|
226
|
+
console.log('ā Deployment cancelled.');
|
|
227
|
+
}
|
|
228
|
+
process.exit(0);
|
|
229
|
+
break;
|
|
230
|
+
|
|
231
|
+
default:
|
|
232
|
+
console.log(`\nā Unknown command: "${command || ''}"`);
|
|
233
|
+
showHelp();
|
|
234
|
+
process.exit(0);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.log(`\nā Process stopped due to error or cancellation.`);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
run();
|