@getik-public/cli 1.0.0
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/CHANGELOG.md +2 -0
- package/README.md +38 -0
- package/bin/index.js +16 -0
- package/package.json +24 -0
- package/src/mobile-build.js +308 -0
- package/src/upload-to-getik-cloud.js +78 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Getik CLI
|
|
2
|
+
`@getik-public/cli` is a collection of scripts meant to ease the development flow. For available scripts read further.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# How to use the cli
|
|
7
|
+
Add next line in your `package.json` file under `devDependencies`:
|
|
8
|
+
`"@getik-public/cli": "X.Y.Z"` or simply run `npm i @getik-public/cli@latest --save-dev`.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Available scripts
|
|
13
|
+
- [`mobile-build`](#mobile-build)
|
|
14
|
+
- [`upload-to-getik-cloud`](#upload-to-getik-cloud)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## <a name="mobile-build" href="#mobile-build">`mobile-build`</a>
|
|
19
|
+
### Usage: `getik-cli mobile-build [-p, --platform] [-e, --environment] [--syncOnly] [--aab] [--upload]`
|
|
20
|
+
Example: `getik-cli mobile-build -p android -e getikDebug --syncOnly`
|
|
21
|
+
Example: `getik-cli mobile-build --platform ios --environment getik --upload`
|
|
22
|
+
|
|
23
|
+
| Option | Required | Values | Description |
|
|
24
|
+
|-----------------------|----------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
25
|
+
| `-p`, `--platform` | YES | `android`, `ios` | Platform to build for. |
|
|
26
|
+
| `-e`, `--environment` | YES | `<string>`, `<string>Debug` | While environment can be any name, be consistent and use these: `getik`, `vbox`, `qa`, `prod`. Every environment must have a pair for debug build, so have these environments also defined: `getikDebug`, `vboxDebug`, `qaDebug`, `prodDebug` |
|
|
27
|
+
| `--syncOnly` | NO | `-` | For development only, if you need to apply javascript build, or a new plugin was added. This will not go further to trigger an build script. |
|
|
28
|
+
| `--aab` | NO | `-` | For `--platform android` only. Build `aab` file instead of `apk` file. |
|
|
29
|
+
| `--upload` | NO | `-` | For `--platform ios` only. Instant upload to store after build, if successful. |
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## <a name="upload-to-getik-cloud" href="#upload-to-getik-cloud">`upload-to-getik-cloud`</a>
|
|
34
|
+
### Usage: `getik-cli upload-to-getik-cloud ./path/to/my-file.apk`
|
|
35
|
+
Use this command to upload apk files to getik cloud. If successful, in command line you will find a direct link to fresh uploaded file alongside a link to the full list.
|
|
36
|
+
Run this command from the root of the project, as it tries to look for project name in `package.json` file. Project name will be used as file name.
|
|
37
|
+
|
|
38
|
+
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import figlet from 'figlet';
|
|
6
|
+
|
|
7
|
+
import { mobileBuild } from '../src/mobile-build.js';
|
|
8
|
+
import { uploadToGetikCloud } from '../src/upload-to-getik-cloud.js';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
console.log(chalk.green(figlet.textSync('Getik CLI', {horizontalLayout: 'full'})));
|
|
12
|
+
|
|
13
|
+
mobileBuild();
|
|
14
|
+
uploadToGetikCloud();
|
|
15
|
+
|
|
16
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@getik-public/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"getik-cli": "./bin/index.js"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"description": "Getik CLI",
|
|
15
|
+
"author": "Getik",
|
|
16
|
+
"license": "Getik",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"chalk": "^5.3.0",
|
|
19
|
+
"commander": "^12.0.0",
|
|
20
|
+
"figlet": "^1.7.0",
|
|
21
|
+
"inquirer": "^9.2.14",
|
|
22
|
+
"ora": "^8.0.1"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const buildFolder = 'build';
|
|
8
|
+
|
|
9
|
+
async function applyPatchersForExternalNpmPackages() {
|
|
10
|
+
const patchesFolderName = '.patchers-for-external-npm-packages';
|
|
11
|
+
const filenameEndsWith = '.patcher.js';
|
|
12
|
+
const patchAppliedMarker = '// PATCH_APPLIED_MARKER_BY_GETIK_CLI_BUILD';
|
|
13
|
+
if (!fs.existsSync(path.join(process.cwd(), patchesFolderName))) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const patchesInFolder = fs.readdirSync(path.join(process.cwd(), patchesFolderName));
|
|
18
|
+
let displayClosingSeparatorLine = false;
|
|
19
|
+
for (const filename of patchesInFolder) {
|
|
20
|
+
if (filename.indexOf(filenameEndsWith) === filename.length - filenameEndsWith.length) {
|
|
21
|
+
const pathToFile = path.join(process.cwd(), patchesFolderName, filename);
|
|
22
|
+
const patcherImport = await import(pathToFile);
|
|
23
|
+
const patcher = patcherImport.default;
|
|
24
|
+
console.log('----------------------------------------------------------------------------------------------------------------------');
|
|
25
|
+
displayClosingSeparatorLine = true;
|
|
26
|
+
console.log('PATCH FOUND FOR ->', patcher.name, ':', patcher.version);
|
|
27
|
+
if (!patcher.name || !patcher.version || !patcher.reason || !patcher.applyPatchFor?.length) {
|
|
28
|
+
showPatcherInvalidFormat()
|
|
29
|
+
}
|
|
30
|
+
checkPatcherForPackageMatch(patcher);
|
|
31
|
+
patcher.applyPatchFor.forEach((patchFile) => {
|
|
32
|
+
if (!patchFile.file || !patchFile.applyPatch) {
|
|
33
|
+
showPatcherInvalidFormat()
|
|
34
|
+
}
|
|
35
|
+
console.log('CHECK IF PATCH APPLIED ->', patcher.name, ':', patcher.version, '-> File:', patchFile.file);
|
|
36
|
+
const filePath = path.join(process.cwd(), ...patchFile.file.split('/'));
|
|
37
|
+
if (!fs.existsSync(filePath)) {
|
|
38
|
+
throw new Error(`Can't apply PATCH for "${patchFile.file}". File not found.`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const fileContent = fs.readFileSync(filePath).toString();
|
|
42
|
+
const patchApplied = (fileContent.indexOf(patchAppliedMarker) === 0);
|
|
43
|
+
|
|
44
|
+
if (patchApplied) {
|
|
45
|
+
console.log('PATCHED ALREADY APPLIED FOR ->', patcher.name, ':', patcher.version, '-> File:', patchFile.file);
|
|
46
|
+
console.log('SKIPPING...');
|
|
47
|
+
} else {
|
|
48
|
+
console.log('APPLYING PATCH FOR ->', patcher.name, ':', patcher.version);
|
|
49
|
+
const patchedFileContent = patchFile.applyPatch(fileContent);
|
|
50
|
+
if (!patchedFileContent || typeof patchedFileContent !=='string') {
|
|
51
|
+
throw new Error(`"applyPatch" must return patched code as a "string". PATCH not applied for ${patchFile.file}`);
|
|
52
|
+
}
|
|
53
|
+
fs.writeFileSync(filePath, (patchAppliedMarker + '\r\n' + patchedFileContent));
|
|
54
|
+
console.log('PATCHED SUCCESSFULLY ->', patcher.name, ':', patcher.version);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (displayClosingSeparatorLine) {
|
|
60
|
+
console.log('----------------------------------------------------------------------------------------------------------------------');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function showPatcherInvalidFormat() {
|
|
66
|
+
const message = `
|
|
67
|
+
Invalid patcher, make sure you have the right format. Example:
|
|
68
|
+
---------------------------------------------------------------------
|
|
69
|
+
const patcher = {
|
|
70
|
+
name: '<PACKAGE_NAME>',
|
|
71
|
+
version: '<VERSION>',
|
|
72
|
+
reason: '<REASON>',
|
|
73
|
+
applyPatchFor: [{
|
|
74
|
+
file: '<PATH_TO_FILE>',
|
|
75
|
+
applyPatch: (fileContent) => {
|
|
76
|
+
const patchedFileContent = '...';
|
|
77
|
+
|
|
78
|
+
return patchedFileContent;
|
|
79
|
+
},
|
|
80
|
+
}],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
module.exports = patcher;
|
|
84
|
+
---------------------------------------------------------------------`;
|
|
85
|
+
|
|
86
|
+
throw new Error(message);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
function checkPatcherForPackageMatch(patcher) {
|
|
91
|
+
const splitNameToFolder = patcher.name.split('/');
|
|
92
|
+
const pathToPackage = path.join('node_modules', ...splitNameToFolder);
|
|
93
|
+
const pathToPackageJson = path.join(pathToPackage, 'package.json');
|
|
94
|
+
const cantApplyErrorMessage = `Can't apply PATCH for "${patcher.name}:${patcher.version}"`;
|
|
95
|
+
|
|
96
|
+
if (!fs.existsSync(pathToPackage) || !fs.existsSync(pathToPackageJson)) {
|
|
97
|
+
throw new Error(`${cantApplyErrorMessage}. Package not FOUND in "node_modules".`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const fileBuffer = fs.readFileSync(pathToPackageJson);
|
|
101
|
+
const packageJson = JSON.parse(fileBuffer);
|
|
102
|
+
if (packageJson.name !== patcher.name) {
|
|
103
|
+
throw new Error(`${cantApplyErrorMessage}. Name in patch is not the same is in "package.json".`);
|
|
104
|
+
}
|
|
105
|
+
if (packageJson.version !== patcher.version) {
|
|
106
|
+
const nextStepsMessage = `You have to check if existing PATCH applies to current version and either update version in patch, or remove path entirely if not required anymore.`;
|
|
107
|
+
throw new Error(`${cantApplyErrorMessage}. You have "${packageJson.version}" version set in "node_modules". ${nextStepsMessage}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
function createCommandsForAndroid(options) {
|
|
113
|
+
const isWindows = (process.platform === 'win32');
|
|
114
|
+
const capitalizedEnvironment = (options.environment.charAt(0).toUpperCase() + options.environment.slice(1));
|
|
115
|
+
const buildType = (options.aab) ? 'bundle' : 'assemble';
|
|
116
|
+
const buildCommand = (isWindows ? `gradlew ${buildType}${capitalizedEnvironment}` : `sh ./gradlew ${buildType}${capitalizedEnvironment}`);
|
|
117
|
+
|
|
118
|
+
return [buildCommand];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
function createCommandsForIos(options) {
|
|
123
|
+
const workspace = './App/App.xcworkspace';
|
|
124
|
+
const debugMode = (options.environment.indexOf("Debug") >= 0);
|
|
125
|
+
const config = (debugMode ? 'Debug' : 'Release');
|
|
126
|
+
const environment = (options.environment.split('Debug')[0]);
|
|
127
|
+
const archive = `./build/archive/${environment}.xcarchive`;
|
|
128
|
+
const exportPlist = `./${environment}-export-options.plist`;
|
|
129
|
+
const build = `./build/exported`;
|
|
130
|
+
const removeBuildFolderCommand = 'rm -rf ./build';
|
|
131
|
+
const archiveCommand = `xcodebuild -workspace ${workspace} -scheme ${environment} -sdk iphoneos -configuration ${config} archive -archivePath ${archive} -allowProvisioningUpdates -quiet`;
|
|
132
|
+
const exportCommand = `xcodebuild -exportArchive -archivePath ${archive} -exportPath ${build} -exportOptionsPlist ${exportPlist} -allowProvisioningUpdates -quiet`;
|
|
133
|
+
const commands = [removeBuildFolderCommand, archiveCommand, exportCommand];
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const sensitiveDataBuffer = fs.readFileSync(path.join('ios', 'sensitive-data.json'));
|
|
137
|
+
const sensitiveData = JSON.parse(sensitiveDataBuffer);
|
|
138
|
+
const username = sensitiveData[environment].username;
|
|
139
|
+
const password = sensitiveData[environment].password;
|
|
140
|
+
const validateIpaCommand = `xcrun altool --validate-app -t ios -f ${build}/${environment}.ipa -u ${username} -p ${password}`;
|
|
141
|
+
commands.push(validateIpaCommand);
|
|
142
|
+
|
|
143
|
+
if (options.upload) {
|
|
144
|
+
const uploadAppCommand = `xcrun altool --upload-app -t ios -f ${build}/${environment}.ipa -u ${username} -p ${password}`;
|
|
145
|
+
commands.push(uploadAppCommand);
|
|
146
|
+
}
|
|
147
|
+
} catch(error) {
|
|
148
|
+
const message = `File "./ios/sensitive-data.json" not found or has an invalid JSON structure.`;
|
|
149
|
+
throw new Error(message);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return commands;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
function cleanBuildFolder(options) {
|
|
157
|
+
const platformBuildFolder = `${buildFolder}/${options.platform}`;
|
|
158
|
+
if (fs.existsSync(buildFolder)) {
|
|
159
|
+
fs.rmSync(buildFolder, {recursive: true});
|
|
160
|
+
}
|
|
161
|
+
fs.mkdirSync(platformBuildFolder, {recursive: true});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
function copyFinalBuildToRootFolder(options) {
|
|
166
|
+
const platformBuildFolder = `${buildFolder}/${options.platform}`;
|
|
167
|
+
const pathToAppBuild = (options.platform === 'ios') ? buildPathToIosBuildFile(options): buildPathToAndroidBuildFile(options);
|
|
168
|
+
fs.copyFileSync(pathToAppBuild.path, path.join(platformBuildFolder, pathToAppBuild.name));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
function buildPathToIosBuildFile() {
|
|
173
|
+
const env = options.environment.toLowerCase().split('debug')[0];
|
|
174
|
+
const filename = `${env}.ipa`;
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
name: filename,
|
|
178
|
+
path: path.join('ios', 'build', 'exported', filename),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
function buildPathToAndroidBuildFile(options) {
|
|
184
|
+
const env = options.environment.toLowerCase().split('debug')[0];
|
|
185
|
+
let fileToCopy;
|
|
186
|
+
|
|
187
|
+
if ((options.aab)) {
|
|
188
|
+
const bundleFolder = ((options.environment.indexOf('Debug') >= 0) ? options.environment : (env + 'Release'));
|
|
189
|
+
const pathToBuild = path.join('android', 'app', 'build', 'outputs', 'bundle', bundleFolder);
|
|
190
|
+
const filesInFolder = fs.readdirSync(pathToBuild);
|
|
191
|
+
filesInFolder.forEach((filename) => {
|
|
192
|
+
if (filename.indexOf('.aab') === filename.length - 4) {
|
|
193
|
+
fileToCopy = {
|
|
194
|
+
name: filename,
|
|
195
|
+
path: path.join(pathToBuild, filename),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
} else {
|
|
200
|
+
const buildType = (options.environment.indexOf('Debug') >= 0) ? `debug` : `release`;
|
|
201
|
+
const pathToBuild = path.join('android', 'app', 'build', 'outputs', 'apk', env, buildType);
|
|
202
|
+
const filesInFolder = fs.readdirSync(pathToBuild);
|
|
203
|
+
filesInFolder.forEach((filename) => {
|
|
204
|
+
if (filename.indexOf('.apk') === filename.length - 4) {
|
|
205
|
+
fileToCopy = {
|
|
206
|
+
name: filename,
|
|
207
|
+
path: path.join(pathToBuild, filename),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!fileToCopy) {
|
|
214
|
+
const message = `Built file not found. This could be because build failed.`;
|
|
215
|
+
throw new Error(message);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return fileToCopy;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
function createCliCommands(options) {
|
|
223
|
+
cleanBuildFolder(options);
|
|
224
|
+
const buildAngular = `ng build --configuration=${options.environment}`;
|
|
225
|
+
const capacitorSync = () => {
|
|
226
|
+
process.env.NODE_ENV = options.environment;
|
|
227
|
+
|
|
228
|
+
return `cap sync ${options.platform}`;
|
|
229
|
+
};
|
|
230
|
+
const cliCommands = {
|
|
231
|
+
buildAngular: buildAngular,
|
|
232
|
+
capacitorSync: capacitorSync,
|
|
233
|
+
buildApp: [],
|
|
234
|
+
};
|
|
235
|
+
if (!options.syncOnly) {
|
|
236
|
+
cliCommands.buildApp = (options.platform === 'android') ? createCommandsForAndroid(options) : createCommandsForIos(options);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return cliCommands;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
function runCliCommand(command, callback, path) {
|
|
244
|
+
console.log('COMMAND: ', '\x1b[96m', command, '\x1b[0m');
|
|
245
|
+
callback = callback || function() {};
|
|
246
|
+
const ls = spawn(command, [], {shell: true, env: { ...process.env, FORCE_COLOR: true }, cwd: path || ''});
|
|
247
|
+
|
|
248
|
+
ls.stdout.on('data', data => {
|
|
249
|
+
console.log(data.toString());
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
ls.stderr.on('data', data => {
|
|
253
|
+
console.log(data.toString());
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
ls.on('error', (error) => {
|
|
257
|
+
console.log(error.message);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
ls.on('close', code => {
|
|
261
|
+
console.log(`child process exited with code ${code}`);
|
|
262
|
+
if (code !== 0) {
|
|
263
|
+
console.log('\x1b[31m');
|
|
264
|
+
throw new Error(`Command FAILED: ${command}`);
|
|
265
|
+
}
|
|
266
|
+
callback();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
function runCliCommandList(list, path, callback) {
|
|
272
|
+
if (list.length === 0) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const currentCommand = list.shift();
|
|
276
|
+
runCliCommand(currentCommand, () => {
|
|
277
|
+
if (list.length === 0) {
|
|
278
|
+
callback();
|
|
279
|
+
}
|
|
280
|
+
runCliCommandList(list, path, callback);
|
|
281
|
+
}, path);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
export const mobileBuild = () => {
|
|
286
|
+
program
|
|
287
|
+
.command('mobile-build')
|
|
288
|
+
.requiredOption('-p, --platform <type>', 'Platform: android, ios')
|
|
289
|
+
.requiredOption('-e, --environment <type>', 'Environment: getik, getikDebug')
|
|
290
|
+
.option('--syncOnly', 'Apply capacitor sync only, without platform build')
|
|
291
|
+
.option('--aab', 'Android platform only, final build as AAB')
|
|
292
|
+
.option('--upload', 'iOS platform only, upload directly to AppStore')
|
|
293
|
+
.action((options) => {
|
|
294
|
+
console.log('INPUT OPTIONS: ', options);
|
|
295
|
+
const cliCommands = createCliCommands(options);
|
|
296
|
+
|
|
297
|
+
applyPatchersForExternalNpmPackages();
|
|
298
|
+
runCliCommand(cliCommands.buildAngular, function () {
|
|
299
|
+
runCliCommand(cliCommands.capacitorSync(), function () {
|
|
300
|
+
runCliCommandList(cliCommands.buildApp, options.platform, () => {
|
|
301
|
+
setTimeout(() => {
|
|
302
|
+
copyFinalBuildToRootFolder(options);
|
|
303
|
+
}, 100);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { execSync, spawn } from 'child_process';
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const upload = (pathToFile) => {
|
|
9
|
+
let projectName = '';
|
|
10
|
+
try {
|
|
11
|
+
const packageJsonBuffer = fs.readFileSync(path.join(process.cwd(), 'package.json'));
|
|
12
|
+
const packageJson = JSON.parse(packageJsonBuffer);
|
|
13
|
+
projectName = packageJson.name;
|
|
14
|
+
} catch (e) {
|
|
15
|
+
const message = 'Failed to read project name from "package.json" file. Make sure the script is run from inside the project(root) and there is a "package.json" file';
|
|
16
|
+
console.log(chalk.red(message));
|
|
17
|
+
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const normalizedPathToFile = path.join(process.cwd(), pathToFile);
|
|
22
|
+
const commit = execSync('git rev-parse HEAD').toString().trim();
|
|
23
|
+
let branch, splitBranchByFolder, splitBranchByName, issue;
|
|
24
|
+
try {
|
|
25
|
+
branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
|
|
26
|
+
if (branch === 'develop' || branch === 'master') {
|
|
27
|
+
issue = branch;
|
|
28
|
+
} else {
|
|
29
|
+
splitBranchByFolder = branch.split('/');
|
|
30
|
+
splitBranchByName = splitBranchByFolder[splitBranchByFolder.length - 1].split('-');
|
|
31
|
+
issue = `${splitBranchByName[0]}-${splitBranchByName[1]}`;
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
throw new Error(`You should be on a branch which contains issue id in it's name or be on master/develop branch`);
|
|
35
|
+
}
|
|
36
|
+
const splitFileName = normalizedPathToFile.split(path.sep);
|
|
37
|
+
const fileNameWithExtension = splitFileName[splitFileName.length - 1];
|
|
38
|
+
const fileNameOnly = fileNameWithExtension.split('.')[0];
|
|
39
|
+
const command = `curl -Ss -F "file=@${normalizedPathToFile}" "https://devs.getik.net/upload-apk/?name=${projectName}-${fileNameOnly}&appVersion=${issue}&commit=${commit}"`;
|
|
40
|
+
|
|
41
|
+
console.log('COMMAND: ', '\x1b[96m', command, '\x1b[0m');
|
|
42
|
+
const ls = spawn(command, [], {shell: true, env: { ...process.env, FORCE_COLOR: true }, cwd: ''});
|
|
43
|
+
|
|
44
|
+
ls.stdout.on('data', (data) => {
|
|
45
|
+
console.log('RESPONSE: ', data.toString());
|
|
46
|
+
try {
|
|
47
|
+
const parsedResponse = JSON.parse(data.toString());
|
|
48
|
+
if (parsedResponse && parsedResponse.status === 'success' && parsedResponse.fileName) {
|
|
49
|
+
console.log(chalk.green(`Link to uploaded file: https://devs.getik.net/vbox/apk/${parsedResponse.fileName}`));
|
|
50
|
+
console.log(chalk.green('Link to list: https://devs.getik.net/vbox/apk/?C=M;O=D'));
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// console.log(e);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
ls.stderr.on('data', data => {
|
|
58
|
+
console.log(data.toString());
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
ls.on('error', (error) => {
|
|
62
|
+
console.log(error.message);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
ls.on('close', code => {
|
|
66
|
+
console.log(`child process exited with code ${code}`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
export const uploadToGetikCloud = () => {
|
|
72
|
+
program
|
|
73
|
+
.command('upload-to-getik-cloud <source>')
|
|
74
|
+
.action((options) => {
|
|
75
|
+
console.log('INPUT OPTIONS: ', options);
|
|
76
|
+
upload(options);
|
|
77
|
+
});
|
|
78
|
+
};
|