expo-release-it 0.0.10 → 0.0.11
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/bin/expo-release-it.mjs +2 -0
- package/build/command/build.js +39 -45
- package/build/command/bump.js +21 -27
- package/build/command/init.js +53 -59
- package/build/command/submit.js +33 -39
- package/build/command/upload.js +33 -39
- package/build/index.js +16 -18
- package/build/util/EnvUtil.js +2 -5
- package/build/util/FileUtil.js +29 -79
- package/build/util/Logger.js +8 -14
- package/build/util/OptionHolder.js +6 -12
- package/build/util/VersionUtil.js +33 -40
- package/build/util/calculateElapsed.js +3 -6
- package/build/util/hydrateKeyholderFileValues.js +4 -7
- package/build/util/iterateAllFilesInGeneratedTemplate.js +8 -11
- package/build/util/setup/prepareAndroid.js +21 -24
- package/build/util/setup/prepareIos.js +15 -18
- package/build/util/setup/promptCommonInputs.js +14 -17
- package/build/util/setup/setup.js +7 -10
- package/build/util/throwError.js +4 -7
- package/package.json +3 -3
- package/bin/expo-release-it.cjs +0 -2
package/build/command/build.js
CHANGED
|
@@ -1,39 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const FileUtil_1 = require("../util/FileUtil");
|
|
15
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
-
const calculateElapsed_1 = require("../util/calculateElapsed");
|
|
17
|
-
const EnvUtil_1 = require("../util/EnvUtil");
|
|
18
|
-
async function build({ options }) {
|
|
19
|
-
Object.assign(OptionHolder_1.OptionHolder.build, options);
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import { prepareAndroid } from '../util/setup/prepareAndroid';
|
|
3
|
+
import { setup } from '../util/setup/setup';
|
|
4
|
+
import { prepareIos } from '../util/setup/prepareIos';
|
|
5
|
+
import { logger } from '../util/logger';
|
|
6
|
+
import { OptionHolder } from '../util/OptionHolder';
|
|
7
|
+
import { spinner, $ } from 'zx';
|
|
8
|
+
import { resolve, remove } from '../util/FileUtil';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { calculateElapsed } from '../util/calculateElapsed';
|
|
11
|
+
import { isWin } from '../util/EnvUtil';
|
|
12
|
+
export async function build({ options }) {
|
|
13
|
+
Object.assign(OptionHolder.build, options);
|
|
20
14
|
const startTime = Date.now();
|
|
21
|
-
await
|
|
15
|
+
await setup();
|
|
22
16
|
await promptInputs();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (
|
|
17
|
+
logger.info('Build Started');
|
|
18
|
+
logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
|
|
19
|
+
if (OptionHolder.build.platform === 'ios') {
|
|
26
20
|
await buildIos();
|
|
27
|
-
|
|
21
|
+
logger.success(`iOS Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
28
22
|
}
|
|
29
23
|
else {
|
|
30
24
|
await buildAndroid();
|
|
31
|
-
|
|
25
|
+
logger.success(`Android Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
32
26
|
}
|
|
33
27
|
}
|
|
34
28
|
async function promptInputs() {
|
|
35
|
-
if (!
|
|
36
|
-
|
|
29
|
+
if (!OptionHolder.build.platform) {
|
|
30
|
+
OptionHolder.build.platform = await select({
|
|
37
31
|
message: 'Platform to release',
|
|
38
32
|
choices: [
|
|
39
33
|
{ name: 'ios', value: 'ios', description: 'Release ios' },
|
|
@@ -41,8 +35,8 @@ async function promptInputs() {
|
|
|
41
35
|
],
|
|
42
36
|
});
|
|
43
37
|
}
|
|
44
|
-
if (
|
|
45
|
-
|
|
38
|
+
if (OptionHolder.build.platform === 'ios') {
|
|
39
|
+
OptionHolder.build.pod = await select({
|
|
46
40
|
message: 'Install Cocoapods',
|
|
47
41
|
choices: [
|
|
48
42
|
{ name: 'yes', value: true, description: 'Install pods before release' },
|
|
@@ -52,36 +46,36 @@ async function promptInputs() {
|
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
48
|
async function buildIos() {
|
|
55
|
-
const iosDir =
|
|
56
|
-
const $$ = (
|
|
49
|
+
const iosDir = resolve(OptionHolder.rootDir, 'ios');
|
|
50
|
+
const $$ = $({
|
|
57
51
|
verbose: false,
|
|
58
52
|
cwd: iosDir,
|
|
59
53
|
env: {
|
|
60
|
-
MATCH_PASSWORD:
|
|
54
|
+
MATCH_PASSWORD: OptionHolder.keyholderFileValueMap.ios_match_password,
|
|
61
55
|
},
|
|
62
56
|
});
|
|
63
|
-
await
|
|
57
|
+
await prepareIos();
|
|
64
58
|
await fastlane();
|
|
65
59
|
async function fastlane() {
|
|
66
|
-
await
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
await
|
|
70
|
-
|
|
60
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
61
|
+
logger.success('Bundler Install');
|
|
62
|
+
if (OptionHolder.build.pod) {
|
|
63
|
+
await spinner('Pod Install', () => $$ `bundle exec pod install`);
|
|
64
|
+
logger.success('Pod Install');
|
|
71
65
|
}
|
|
72
|
-
|
|
73
|
-
await
|
|
66
|
+
remove(resolve(iosDir, '.xcode.env.local'));
|
|
67
|
+
await spinner('Fastlane', () => $$ `bundle exec fastlane build version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
|
|
74
68
|
}
|
|
75
69
|
}
|
|
76
70
|
async function buildAndroid() {
|
|
77
|
-
const $$ = (
|
|
71
|
+
const $$ = $({
|
|
78
72
|
verbose: false,
|
|
79
|
-
cwd:
|
|
73
|
+
cwd: resolve(OptionHolder.rootDir, 'android'),
|
|
80
74
|
});
|
|
81
|
-
await
|
|
75
|
+
await prepareAndroid();
|
|
82
76
|
await fastlane();
|
|
83
77
|
async function fastlane() {
|
|
84
|
-
await
|
|
85
|
-
await
|
|
78
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
79
|
+
await spinner('Bundle AAB', () => $$ `${isWin ? 'gradle.bat' : './gradlew'} app:bundleRelease`);
|
|
86
80
|
}
|
|
87
81
|
}
|
package/build/command/bump.js
CHANGED
|
@@ -1,44 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const semver_1 = __importDefault(require("semver"));
|
|
12
|
-
const EnvUtil_1 = require("../util/EnvUtil");
|
|
13
|
-
const zx_1 = require("zx");
|
|
14
|
-
const setup_1 = require("../util/setup/setup");
|
|
15
|
-
async function bump({ options }) {
|
|
16
|
-
Object.assign(OptionHolder_1.OptionHolder.bump, options);
|
|
1
|
+
import { injectBinaryVersions } from '../util/VersionUtil';
|
|
2
|
+
import { throwError } from '../util/throwError';
|
|
3
|
+
import { logger } from '../util/logger';
|
|
4
|
+
import { OptionHolder } from '../util/OptionHolder';
|
|
5
|
+
import semver from 'semver';
|
|
6
|
+
import { isDev } from '../util/EnvUtil';
|
|
7
|
+
import { $ } from 'zx';
|
|
8
|
+
import { setup } from '../util/setup/setup';
|
|
9
|
+
export async function bump({ options }) {
|
|
10
|
+
Object.assign(OptionHolder.bump, options);
|
|
17
11
|
await preCheck();
|
|
18
|
-
await
|
|
19
|
-
|
|
20
|
-
const nextVersionName =
|
|
21
|
-
const nextVersionCode = Number(
|
|
22
|
-
|
|
23
|
-
await
|
|
24
|
-
|
|
12
|
+
await setup();
|
|
13
|
+
logger.info(`current version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
|
|
14
|
+
const nextVersionName = semver.inc(OptionHolder.versionName, 'patch');
|
|
15
|
+
const nextVersionCode = Number(OptionHolder.versionCode) + 1 + '';
|
|
16
|
+
logger.info(`next version: ${nextVersionName}(${nextVersionCode})`);
|
|
17
|
+
await injectBinaryVersions({ versionName: nextVersionName, versionCode: nextVersionCode });
|
|
18
|
+
logger.success('Binary versions have been bumped in expo config file');
|
|
25
19
|
}
|
|
26
20
|
async function preCheck() {
|
|
27
|
-
if (
|
|
21
|
+
if (isDev)
|
|
28
22
|
return;
|
|
29
23
|
try {
|
|
30
24
|
let hasChange = false;
|
|
31
25
|
try {
|
|
32
|
-
await
|
|
26
|
+
await $ `git diff --quiet HEAD`;
|
|
33
27
|
}
|
|
34
28
|
catch (_) {
|
|
35
29
|
hasChange = true;
|
|
36
30
|
}
|
|
37
31
|
if (hasChange) {
|
|
38
|
-
|
|
32
|
+
throwError('Workspace is not clean. Before bump version, you should commit all changes.');
|
|
39
33
|
}
|
|
40
34
|
}
|
|
41
35
|
catch (e) {
|
|
42
|
-
|
|
36
|
+
throwError('Precheck Failed', e);
|
|
43
37
|
}
|
|
44
38
|
}
|
package/build/command/init.js
CHANGED
|
@@ -1,106 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const zx_1 = require("zx");
|
|
17
|
-
async function init({ options }) {
|
|
18
|
-
Object.assign(OptionHolder_1.OptionHolder.init, options);
|
|
19
|
-
logger_1.logger.info(`${chalk_1.default.inverse('expo-local-build')}`);
|
|
20
|
-
await (0, promptCommonInputs_1.promptCommonInputs)();
|
|
21
|
-
await (0, VersionUtil_1.parseBinaryVersions)();
|
|
1
|
+
import { OptionHolder } from '../util/OptionHolder';
|
|
2
|
+
import { logger } from '../util/logger';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { input } from '@inquirer/prompts';
|
|
5
|
+
import { iterateAllFilesInGeneratedTemplate } from '../util/iterateAllFilesInGeneratedTemplate';
|
|
6
|
+
import { isDev } from '../util/EnvUtil';
|
|
7
|
+
import { parseBinaryVersions } from '../util/VersionUtil';
|
|
8
|
+
import { promptCommonInputs } from '../util/setup/promptCommonInputs';
|
|
9
|
+
import { exist, remove, copy, read, write, join, writeJson } from '../util/FileUtil';
|
|
10
|
+
import { path } from 'zx';
|
|
11
|
+
export async function init({ options }) {
|
|
12
|
+
Object.assign(OptionHolder.init, options);
|
|
13
|
+
logger.info(`${chalk.inverse('expo-local-build')}`);
|
|
14
|
+
await promptCommonInputs();
|
|
15
|
+
await parseBinaryVersions();
|
|
22
16
|
await promptInputs();
|
|
23
17
|
await copyTemplates();
|
|
24
18
|
await injectPlaceHolders();
|
|
25
|
-
|
|
19
|
+
logger.success('expo-local-build init success');
|
|
26
20
|
}
|
|
27
21
|
async function promptInputs() {
|
|
28
22
|
/* ios */
|
|
29
|
-
|
|
30
|
-
await
|
|
23
|
+
OptionHolder.iosBundleIdentifier = OptionHolder.templateValuePlaceholderMap.ios_app_identifier =
|
|
24
|
+
await input({
|
|
31
25
|
message: 'IOS Bundle Identifier',
|
|
32
26
|
required: true,
|
|
33
|
-
default:
|
|
27
|
+
default: isDev ? 'ios_app_identifier' : undefined,
|
|
34
28
|
});
|
|
35
|
-
|
|
29
|
+
OptionHolder.templateValuePlaceholderMap.ios_app_store_connect_team_id = await input({
|
|
36
30
|
message: 'IOS App Store Connect Team Id',
|
|
37
|
-
default:
|
|
31
|
+
default: isDev ? 'ios_app_store_connect_team_id' : undefined,
|
|
38
32
|
});
|
|
39
|
-
|
|
33
|
+
OptionHolder.templateValuePlaceholderMap.ios_developer_team_id = await input({
|
|
40
34
|
message: 'IOS Developer Portal Team Id',
|
|
41
|
-
default:
|
|
35
|
+
default: isDev ? 'ios_developer_team_id' : undefined,
|
|
42
36
|
});
|
|
43
|
-
|
|
37
|
+
OptionHolder.templateValuePlaceholderMap.ios_match_git_url = await input({
|
|
44
38
|
message: 'IOS Match Key Storage Github URL',
|
|
45
|
-
default:
|
|
39
|
+
default: isDev ? 'ios_match_git_url' : undefined,
|
|
46
40
|
});
|
|
47
|
-
|
|
41
|
+
OptionHolder.keyholderFileValueMap.ios_match_password = await input({
|
|
48
42
|
message: 'IOS Match Password',
|
|
49
|
-
default:
|
|
43
|
+
default: isDev ? 'ios_match_password' : undefined,
|
|
50
44
|
});
|
|
51
|
-
|
|
45
|
+
OptionHolder.templateValuePlaceholderMap.ios_app_store_connect_api_key_id = await input({
|
|
52
46
|
message: 'IOS App Store Connect Api Key Id',
|
|
53
|
-
default:
|
|
47
|
+
default: isDev ? 'ios_app_store_connect_api_key_id' : undefined,
|
|
54
48
|
});
|
|
55
|
-
|
|
49
|
+
OptionHolder.templateValuePlaceholderMap.ios_app_store_connect_api_key_issuer_id = await input({
|
|
56
50
|
message: 'IOS App Store Connect Api Key Issuer Id',
|
|
57
|
-
default:
|
|
51
|
+
default: isDev ? 'ios_app_store_connect_api_key_issuer_id' : undefined,
|
|
58
52
|
});
|
|
59
|
-
|
|
53
|
+
OptionHolder.templateValuePlaceholderMap.ios_xcode_project_target = await input({
|
|
60
54
|
message: 'IOS Xcode Target Name',
|
|
61
55
|
default: 'app',
|
|
62
56
|
});
|
|
63
57
|
/* android */
|
|
64
|
-
|
|
65
|
-
await
|
|
58
|
+
OptionHolder.androidPackageName = OptionHolder.templateValuePlaceholderMap.android_package_name =
|
|
59
|
+
await input({
|
|
66
60
|
message: 'Android Package Name',
|
|
67
|
-
default:
|
|
61
|
+
default: isDev ? 'android_package_name' : undefined,
|
|
68
62
|
});
|
|
69
|
-
|
|
63
|
+
OptionHolder.keyholderFileValueMap.android_keystore_store_password = await input({
|
|
70
64
|
message: 'Android Keystore Store Password',
|
|
71
|
-
default:
|
|
65
|
+
default: isDev ? 'android_keystore_store_password' : undefined,
|
|
72
66
|
});
|
|
73
|
-
|
|
67
|
+
OptionHolder.keyholderFileValueMap.android_keystore_key_alias = await input({
|
|
74
68
|
message: 'Android Keystore Key Alias',
|
|
75
|
-
default:
|
|
69
|
+
default: isDev ? 'android_keystore_key_alias' : undefined,
|
|
76
70
|
});
|
|
77
|
-
|
|
71
|
+
OptionHolder.keyholderFileValueMap.android_keystore_key_password = await input({
|
|
78
72
|
message: 'Android Keystore Key Password',
|
|
79
|
-
default:
|
|
73
|
+
default: isDev ? 'android_keystore_key_password' : undefined,
|
|
80
74
|
});
|
|
81
|
-
|
|
75
|
+
writeJson(OptionHolder.keyholderFilePath, OptionHolder.keyholderFileValueMap);
|
|
82
76
|
}
|
|
83
77
|
async function copyTemplates() {
|
|
84
|
-
for (const dir of
|
|
78
|
+
for (const dir of OptionHolder.templateDirNames) {
|
|
85
79
|
await copyDirRecursively(dir);
|
|
86
80
|
}
|
|
87
81
|
async function copyDirRecursively(dir) {
|
|
88
|
-
const sourceDirPath =
|
|
89
|
-
const destDirPath =
|
|
90
|
-
if (
|
|
91
|
-
|
|
82
|
+
const sourceDirPath = join(OptionHolder.cli.templateDir, dir);
|
|
83
|
+
const destDirPath = join(OptionHolder.outDir, dir);
|
|
84
|
+
if (exist(destDirPath)) {
|
|
85
|
+
remove(destDirPath);
|
|
92
86
|
}
|
|
93
|
-
|
|
87
|
+
copy(sourceDirPath, destDirPath);
|
|
94
88
|
}
|
|
95
89
|
}
|
|
96
90
|
async function injectPlaceHolders() {
|
|
97
|
-
await
|
|
98
|
-
let content =
|
|
99
|
-
for (const [key, value] of Object.entries(
|
|
91
|
+
await iterateAllFilesInGeneratedTemplate(async (filePath) => {
|
|
92
|
+
let content = read(filePath);
|
|
93
|
+
for (const [key, value] of Object.entries(OptionHolder.templateValuePlaceholderMap)) {
|
|
100
94
|
content = content.replaceAll(`{{${key}}}`, value);
|
|
101
95
|
}
|
|
102
96
|
// dynamic replace
|
|
103
|
-
content = content.replaceAll('{{key_dir_relative_path}}',
|
|
104
|
-
|
|
97
|
+
content = content.replaceAll('{{key_dir_relative_path}}', path.relative(filePath, OptionHolder.keyDir));
|
|
98
|
+
write(filePath, content);
|
|
105
99
|
});
|
|
106
100
|
}
|
package/build/command/submit.js
CHANGED
|
@@ -1,38 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const zx_1 = require("zx");
|
|
14
|
-
const prepareAndroid_1 = require("../util/setup/prepareAndroid");
|
|
15
|
-
const FileUtil_1 = require("../util/FileUtil");
|
|
16
|
-
const prepareIos_1 = require("../util/setup/prepareIos");
|
|
17
|
-
async function submit({ options }) {
|
|
18
|
-
Object.assign(OptionHolder_1.OptionHolder.submit, options);
|
|
1
|
+
import { setup } from '../util/setup/setup';
|
|
2
|
+
import { select } from '@inquirer/prompts';
|
|
3
|
+
import { logger } from '../util/logger';
|
|
4
|
+
import { OptionHolder } from '../util/OptionHolder';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { calculateElapsed } from '../util/calculateElapsed';
|
|
7
|
+
import { spinner, $ } from 'zx';
|
|
8
|
+
import { prepareAndroid } from '../util/setup/prepareAndroid';
|
|
9
|
+
import { remove, resolve } from '../util/FileUtil';
|
|
10
|
+
import { prepareIos } from '../util/setup/prepareIos';
|
|
11
|
+
export async function submit({ options }) {
|
|
12
|
+
Object.assign(OptionHolder.submit, options);
|
|
19
13
|
const startTime = Date.now();
|
|
20
|
-
await
|
|
14
|
+
await setup();
|
|
21
15
|
await promptInputs();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
16
|
+
logger.info('Submit Started');
|
|
17
|
+
logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
|
|
18
|
+
if (OptionHolder.submit.platform === 'ios') {
|
|
25
19
|
await submitIos();
|
|
26
|
-
|
|
20
|
+
logger.success(`Appstore Review Submitted ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
27
21
|
}
|
|
28
22
|
else {
|
|
29
23
|
await submitAndroid();
|
|
30
|
-
|
|
24
|
+
logger.success(`Playstore Review Submitted ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
27
|
async function promptInputs() {
|
|
34
|
-
if (!
|
|
35
|
-
|
|
28
|
+
if (!OptionHolder.submit.platform) {
|
|
29
|
+
OptionHolder.submit.platform = await select({
|
|
36
30
|
message: 'Platform to submit',
|
|
37
31
|
choices: [
|
|
38
32
|
{ name: 'ios', value: 'ios', description: 'Release ios' },
|
|
@@ -42,30 +36,30 @@ async function promptInputs() {
|
|
|
42
36
|
}
|
|
43
37
|
}
|
|
44
38
|
async function submitAndroid() {
|
|
45
|
-
const $$ = (
|
|
39
|
+
const $$ = $({
|
|
46
40
|
verbose: false,
|
|
47
|
-
cwd:
|
|
41
|
+
cwd: resolve(OptionHolder.rootDir, 'android'),
|
|
48
42
|
});
|
|
49
|
-
await
|
|
43
|
+
await prepareAndroid();
|
|
50
44
|
await fastlane();
|
|
51
45
|
async function fastlane() {
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
await
|
|
46
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
47
|
+
logger.success('Bundler Install');
|
|
48
|
+
await spinner('Fastlane', () => $$ `bundle exec fastlane submit_playstore_review version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
|
|
55
49
|
}
|
|
56
50
|
}
|
|
57
51
|
async function submitIos() {
|
|
58
|
-
const iosDir =
|
|
59
|
-
const $$ = (
|
|
52
|
+
const iosDir = resolve(OptionHolder.rootDir, 'ios');
|
|
53
|
+
const $$ = $({
|
|
60
54
|
verbose: false,
|
|
61
55
|
cwd: iosDir,
|
|
62
56
|
});
|
|
63
|
-
await
|
|
57
|
+
await prepareIos();
|
|
64
58
|
await fastlane();
|
|
65
59
|
async function fastlane() {
|
|
66
|
-
await
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
await
|
|
60
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
61
|
+
logger.success('Bundler Install');
|
|
62
|
+
remove(resolve(iosDir, '.xcode.env.local'));
|
|
63
|
+
await spinner('Fastlane', () => $$ `bundle exec fastlane submit_appstore_review version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
|
|
70
64
|
}
|
|
71
65
|
}
|
package/build/command/upload.js
CHANGED
|
@@ -1,38 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const zx_1 = require("zx");
|
|
14
|
-
const FileUtil_1 = require("../util/FileUtil");
|
|
15
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
-
const calculateElapsed_1 = require("../util/calculateElapsed");
|
|
17
|
-
async function upload({ options }) {
|
|
18
|
-
Object.assign(OptionHolder_1.OptionHolder.upload, options);
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import { prepareAndroid } from '../util/setup/prepareAndroid';
|
|
3
|
+
import { setup } from '../util/setup/setup';
|
|
4
|
+
import { prepareIos } from '../util/setup/prepareIos';
|
|
5
|
+
import { logger } from '../util/logger';
|
|
6
|
+
import { OptionHolder } from '../util/OptionHolder';
|
|
7
|
+
import { spinner, $ } from 'zx';
|
|
8
|
+
import { resolve } from '../util/FileUtil';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { calculateElapsed } from '../util/calculateElapsed';
|
|
11
|
+
export async function upload({ options }) {
|
|
12
|
+
Object.assign(OptionHolder.upload, options);
|
|
19
13
|
const startTime = Date.now();
|
|
20
|
-
await
|
|
14
|
+
await setup();
|
|
21
15
|
await promptInputs();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
16
|
+
logger.info('Build & Upload Started');
|
|
17
|
+
logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
|
|
18
|
+
if (OptionHolder.upload.platform === 'ios') {
|
|
25
19
|
await uploadIos();
|
|
26
|
-
|
|
20
|
+
logger.success(`iOS Upload ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
27
21
|
}
|
|
28
22
|
else {
|
|
29
23
|
await uploadAndroid();
|
|
30
|
-
|
|
24
|
+
logger.success(`Android Upload ${chalk.bold.inverse(calculateElapsed(startTime))}`);
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
27
|
async function promptInputs() {
|
|
34
|
-
if (!
|
|
35
|
-
|
|
28
|
+
if (!OptionHolder.upload.platform) {
|
|
29
|
+
OptionHolder.upload.platform = await select({
|
|
36
30
|
message: 'Platform to release',
|
|
37
31
|
choices: [
|
|
38
32
|
{ name: 'ios', value: 'ios', description: 'Release ios' },
|
|
@@ -42,32 +36,32 @@ async function promptInputs() {
|
|
|
42
36
|
}
|
|
43
37
|
}
|
|
44
38
|
async function uploadIos() {
|
|
45
|
-
const iosDir =
|
|
46
|
-
const $$ = (
|
|
39
|
+
const iosDir = resolve(OptionHolder.rootDir, 'ios');
|
|
40
|
+
const $$ = $({
|
|
47
41
|
verbose: false,
|
|
48
42
|
cwd: iosDir,
|
|
49
43
|
env: {
|
|
50
|
-
MATCH_PASSWORD:
|
|
44
|
+
MATCH_PASSWORD: OptionHolder.keyholderFileValueMap.ios_match_password,
|
|
51
45
|
},
|
|
52
46
|
});
|
|
53
|
-
await
|
|
47
|
+
await prepareIos();
|
|
54
48
|
await fastlane();
|
|
55
49
|
async function fastlane() {
|
|
56
|
-
await
|
|
57
|
-
|
|
58
|
-
await
|
|
50
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
51
|
+
logger.success('Bundler Install');
|
|
52
|
+
await spinner('Fastlane', () => $$ `bundle exec fastlane upload version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
|
|
59
53
|
}
|
|
60
54
|
}
|
|
61
55
|
async function uploadAndroid() {
|
|
62
|
-
const $$ = (
|
|
56
|
+
const $$ = $({
|
|
63
57
|
verbose: false,
|
|
64
|
-
cwd:
|
|
58
|
+
cwd: resolve(OptionHolder.rootDir, 'android'),
|
|
65
59
|
});
|
|
66
|
-
await
|
|
60
|
+
await prepareAndroid();
|
|
67
61
|
await fastlane();
|
|
68
62
|
async function fastlane() {
|
|
69
|
-
await
|
|
70
|
-
|
|
71
|
-
await
|
|
63
|
+
await spinner('Bundler Install', () => $$ `bundle install`);
|
|
64
|
+
logger.success('Bundler Install');
|
|
65
|
+
await spinner('Fastlane Supply', () => $$ `bundle exec fastlane deploy version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
|
|
72
66
|
}
|
|
73
67
|
}
|
package/build/index.js
CHANGED
|
@@ -1,30 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const submit_1 = require("./command/submit");
|
|
10
|
-
const platformOption = new commander_1.Option('-p --platform <platform>', 'Platform').choices([
|
|
1
|
+
import { Command, Option } from 'commander';
|
|
2
|
+
import { init } from './command/init';
|
|
3
|
+
import { OptionHolder } from './util/OptionHolder';
|
|
4
|
+
import { logger } from './util/logger';
|
|
5
|
+
import { bump } from './command/bump';
|
|
6
|
+
import { upload } from './command/upload';
|
|
7
|
+
import { submit } from './command/submit';
|
|
8
|
+
const platformOption = new Option('-p --platform <platform>', 'Platform').choices([
|
|
11
9
|
'android',
|
|
12
10
|
'ios',
|
|
13
11
|
]);
|
|
14
|
-
const program = new
|
|
12
|
+
const program = new Command();
|
|
15
13
|
program
|
|
16
14
|
.name('expo-release-it')
|
|
17
15
|
.description('Build & Upload & Submit locally for Expo project')
|
|
18
|
-
.version(
|
|
16
|
+
.version(OptionHolder.cli.version);
|
|
19
17
|
program
|
|
20
18
|
.command('init')
|
|
21
19
|
.description('Initialize CLI utilities')
|
|
22
20
|
.action(async (options) => {
|
|
23
21
|
try {
|
|
24
|
-
await
|
|
22
|
+
await init({ options });
|
|
25
23
|
}
|
|
26
24
|
catch (e) {
|
|
27
|
-
|
|
25
|
+
logger.error(e);
|
|
28
26
|
}
|
|
29
27
|
});
|
|
30
28
|
program
|
|
@@ -34,27 +32,27 @@ program
|
|
|
34
32
|
// new Option('-i --increment <type>', 'increment type').choices(['major', 'minor', 'patch']),
|
|
35
33
|
// )
|
|
36
34
|
.action(async (options) => {
|
|
37
|
-
await
|
|
35
|
+
await bump({ options });
|
|
38
36
|
});
|
|
39
37
|
program
|
|
40
38
|
.command('build')
|
|
41
39
|
.description('Build binary')
|
|
42
40
|
.addOption(platformOption)
|
|
43
41
|
.action(async (options) => {
|
|
44
|
-
await
|
|
42
|
+
await upload({ options });
|
|
45
43
|
});
|
|
46
44
|
program
|
|
47
45
|
.command('upload')
|
|
48
46
|
.description('Upload artifact to play console internal test track(android) and testflight(ios)')
|
|
49
47
|
.addOption(platformOption)
|
|
50
48
|
.action(async (options) => {
|
|
51
|
-
await
|
|
49
|
+
await upload({ options });
|
|
52
50
|
});
|
|
53
51
|
program
|
|
54
52
|
.command('submit')
|
|
55
53
|
.description('Submit Google Play Console & App Store Connect Review with latest testing track')
|
|
56
54
|
.addOption(platformOption)
|
|
57
55
|
.action(async (options) => {
|
|
58
|
-
await
|
|
56
|
+
await submit({ options });
|
|
59
57
|
});
|
|
60
58
|
program.parse();
|
package/build/util/EnvUtil.js
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.isWin = exports.isDev = void 0;
|
|
4
|
-
exports.isDev = process.env.NODE_ENV === 'development';
|
|
5
|
-
exports.isWin = process.platform.startsWith('win');
|
|
1
|
+
export const isDev = process.env.NODE_ENV === 'development';
|
|
2
|
+
export const isWin = process.platform.startsWith('win');
|
package/build/util/FileUtil.js
CHANGED
|
@@ -1,106 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.filename = exports.resolve = exports.join = void 0;
|
|
40
|
-
exports.exist = exist;
|
|
41
|
-
exports.isDir = isDir;
|
|
42
|
-
exports.isFile = isFile;
|
|
43
|
-
exports.read = read;
|
|
44
|
-
exports.readdir = readdir;
|
|
45
|
-
exports.readJsonSlow = readJsonSlow;
|
|
46
|
-
exports.write = write;
|
|
47
|
-
exports.copy = copy;
|
|
48
|
-
exports.writeJson = writeJson;
|
|
49
|
-
exports.remove = remove;
|
|
50
|
-
exports.iterateDir = iterateDir;
|
|
51
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
52
|
-
const path = __importStar(require("path"));
|
|
53
|
-
exports.join = path.join;
|
|
54
|
-
exports.resolve = path.resolve;
|
|
55
|
-
exports.filename = path.basename(__filename);
|
|
56
|
-
function exist(path) {
|
|
57
|
-
return fs_extra_1.default.existsSync(path);
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
export const join = path.join;
|
|
4
|
+
export const resolve = path.resolve;
|
|
5
|
+
export const filename = path.basename(__filename);
|
|
6
|
+
export function exist(path) {
|
|
7
|
+
return fs.existsSync(path);
|
|
58
8
|
}
|
|
59
|
-
function isDir(path) {
|
|
60
|
-
return exist(path) &&
|
|
9
|
+
export function isDir(path) {
|
|
10
|
+
return exist(path) && fs.lstatSync(path).isDirectory();
|
|
61
11
|
}
|
|
62
|
-
function isFile(path) {
|
|
63
|
-
return exist(path) &&
|
|
12
|
+
export function isFile(path) {
|
|
13
|
+
return exist(path) && fs.lstatSync(path).isFile();
|
|
64
14
|
}
|
|
65
|
-
function read(path) {
|
|
66
|
-
return
|
|
15
|
+
export function read(path) {
|
|
16
|
+
return fs.readFileSync(path, { encoding: 'utf8' });
|
|
67
17
|
}
|
|
68
|
-
function readdir(path) {
|
|
69
|
-
return
|
|
18
|
+
export function readdir(path) {
|
|
19
|
+
return fs.readdirSync(path);
|
|
70
20
|
}
|
|
71
21
|
// you should require when possible(optimized in js)
|
|
72
|
-
function readJsonSlow(path) {
|
|
73
|
-
return
|
|
22
|
+
export function readJsonSlow(path) {
|
|
23
|
+
return fs.readJSONSync(path);
|
|
74
24
|
}
|
|
75
|
-
function write(p, content) {
|
|
25
|
+
export function write(p, content) {
|
|
76
26
|
const dir = path.dirname(p);
|
|
77
27
|
if (!exist(dir)) {
|
|
78
|
-
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
79
29
|
}
|
|
80
|
-
return
|
|
30
|
+
return fs.writeFileSync(p, content);
|
|
81
31
|
}
|
|
82
|
-
function copy(src, dest) {
|
|
83
|
-
|
|
32
|
+
export function copy(src, dest) {
|
|
33
|
+
fs.copySync(src, dest);
|
|
84
34
|
}
|
|
85
|
-
function writeJson(path, json) {
|
|
35
|
+
export function writeJson(path, json) {
|
|
86
36
|
return write(path, JSON.stringify(json, null, 2));
|
|
87
37
|
}
|
|
88
|
-
function remove(path) {
|
|
38
|
+
export function remove(path) {
|
|
89
39
|
if (!exist(path)) {
|
|
90
40
|
return;
|
|
91
41
|
}
|
|
92
|
-
if (
|
|
93
|
-
return
|
|
42
|
+
if (fs.lstatSync(path).isDirectory()) {
|
|
43
|
+
return fs.rmSync(path, { force: true, recursive: true });
|
|
94
44
|
}
|
|
95
45
|
else {
|
|
96
|
-
return
|
|
46
|
+
return fs.rmSync(path, { force: true });
|
|
97
47
|
}
|
|
98
48
|
}
|
|
99
|
-
async function iterateDir(path, fn) {
|
|
49
|
+
export async function iterateDir(path, fn) {
|
|
100
50
|
if (!isDir(path)) {
|
|
101
51
|
return;
|
|
102
52
|
}
|
|
103
|
-
for (const file of
|
|
53
|
+
for (const file of fs.readdirSync(path)) {
|
|
104
54
|
await fn(file);
|
|
105
55
|
}
|
|
106
56
|
}
|
package/build/util/Logger.js
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
success: (...msg) => console.log(chalk_1.default.green(`✔ ${msg.join(', ')}`)),
|
|
10
|
-
error: (...msg) => console.log(chalk_1.default.red(`✖ ${msg.join(', ')}`)),
|
|
11
|
-
warn: (...msg) => console.log(chalk_1.default.yellow(`⚠ ${msg.join(', ')}`)),
|
|
12
|
-
info: (...msg) => console.log(chalk_1.default.cyan(`ℹ ${msg.join(', ')}`)),
|
|
13
|
-
title: (...msg) => console.log(chalk_1.default.bold.blue(`\n${msg.join(', ')}`)),
|
|
14
|
-
dim: (...msg) => console.log(chalk_1.default.dim(msg.join(', '))),
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const logger = {
|
|
3
|
+
success: (...msg) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),
|
|
4
|
+
error: (...msg) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),
|
|
5
|
+
warn: (...msg) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),
|
|
6
|
+
info: (...msg) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),
|
|
7
|
+
title: (...msg) => console.log(chalk.bold.blue(`\n${msg.join(', ')}`)),
|
|
8
|
+
dim: (...msg) => console.log(chalk.dim(msg.join(', '))),
|
|
15
9
|
};
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.OptionHolder = void 0;
|
|
7
|
-
const package_json_1 = __importDefault(require("../../package.json"));
|
|
8
|
-
const FileUtil_1 = require("./FileUtil");
|
|
1
|
+
import pkgJson from '../../package.json';
|
|
2
|
+
import { resolve } from './FileUtil';
|
|
9
3
|
/**
|
|
10
4
|
* CLI Comprehensive options
|
|
11
5
|
* Each values can be empty by command and timing.
|
|
12
6
|
*/
|
|
13
|
-
|
|
7
|
+
export const OptionHolder = {
|
|
14
8
|
cli: {
|
|
15
|
-
version:
|
|
16
|
-
rootDir:
|
|
17
|
-
templateDir:
|
|
9
|
+
version: pkgJson.version,
|
|
10
|
+
rootDir: resolve(__dirname, '../..'),
|
|
11
|
+
templateDir: resolve(__dirname, '../../template'),
|
|
18
12
|
},
|
|
19
13
|
init: {},
|
|
20
14
|
bump: {},
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.injectBinaryVersions = injectBinaryVersions;
|
|
8
|
-
const OptionHolder_1 = require("./OptionHolder");
|
|
9
|
-
const throwError_1 = require("./throwError");
|
|
10
|
-
const semver_1 = __importDefault(require("semver"));
|
|
11
|
-
const FileUtil_1 = require("./FileUtil");
|
|
12
|
-
async function parseBinaryVersions() {
|
|
13
|
-
const files = (0, FileUtil_1.readdir)(OptionHolder_1.OptionHolder.rootDir);
|
|
1
|
+
import { OptionHolder } from './OptionHolder';
|
|
2
|
+
import { throwError } from './throwError';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
import { readdir, read, readJsonSlow, write, writeJson, resolve } from './FileUtil';
|
|
5
|
+
export async function parseBinaryVersions() {
|
|
6
|
+
const files = readdir(OptionHolder.rootDir);
|
|
14
7
|
const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];
|
|
15
8
|
const jsonConfigFile = 'app.json';
|
|
16
9
|
for (const jsConfigFile of jsConfigFiles) {
|
|
@@ -23,48 +16,48 @@ async function parseBinaryVersions() {
|
|
|
23
16
|
await parseFromJsonConfigFile(jsonConfigFile);
|
|
24
17
|
return;
|
|
25
18
|
}
|
|
26
|
-
|
|
19
|
+
throwError('expo config file not found');
|
|
27
20
|
async function parseFromJsConfigFile(filename) {
|
|
28
|
-
const filePath =
|
|
29
|
-
const content =
|
|
21
|
+
const filePath = resolve(OptionHolder.rootDir, filename);
|
|
22
|
+
const content = read(filePath);
|
|
30
23
|
const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];
|
|
31
24
|
const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];
|
|
32
25
|
if (!VERSION_NAME) {
|
|
33
|
-
|
|
26
|
+
throwError('cannot parse version name');
|
|
34
27
|
}
|
|
35
28
|
if (!VERSION_CODE) {
|
|
36
|
-
|
|
29
|
+
throwError('cannot parse version code');
|
|
37
30
|
}
|
|
38
|
-
if (!
|
|
39
|
-
|
|
31
|
+
if (!semver.valid(VERSION_NAME)) {
|
|
32
|
+
throwError('VERSION_NAME is not a valid semver format');
|
|
40
33
|
}
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
OptionHolder.versionName = VERSION_NAME;
|
|
35
|
+
OptionHolder.versionCode = VERSION_CODE;
|
|
43
36
|
}
|
|
44
37
|
async function parseFromJsonConfigFile(filename) {
|
|
45
|
-
const filePath =
|
|
46
|
-
const json =
|
|
38
|
+
const filePath = resolve(OptionHolder.rootDir, filename);
|
|
39
|
+
const json = readJsonSlow(filePath);
|
|
47
40
|
const versionName = json.expo?.version + '';
|
|
48
41
|
const iosVersionCode = json.expo?.ios?.buildNumber + '';
|
|
49
42
|
const androidVersionCode = json.expo?.android?.versionCode + '';
|
|
50
43
|
if (!/\d+/.test(iosVersionCode)) {
|
|
51
|
-
|
|
44
|
+
throwError('app.json expo.ios.buildNumber is not an integer');
|
|
52
45
|
}
|
|
53
46
|
if (!/\d+/.test(androidVersionCode)) {
|
|
54
|
-
|
|
47
|
+
throwError('app.json expo.android.versionCode is not an integer');
|
|
55
48
|
}
|
|
56
49
|
if (iosVersionCode !== androidVersionCode) {
|
|
57
|
-
|
|
50
|
+
throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');
|
|
58
51
|
}
|
|
59
|
-
if (!
|
|
60
|
-
|
|
52
|
+
if (!semver.valid(versionName)) {
|
|
53
|
+
throwError('VERSION_NAME is not a valid semver format');
|
|
61
54
|
}
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
OptionHolder.versionName = versionName;
|
|
56
|
+
OptionHolder.versionCode = iosVersionCode;
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
|
-
async function injectBinaryVersions({ versionCode, versionName, }) {
|
|
67
|
-
const files =
|
|
59
|
+
export async function injectBinaryVersions({ versionCode, versionName, }) {
|
|
60
|
+
const files = readdir(OptionHolder.rootDir);
|
|
68
61
|
const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];
|
|
69
62
|
const jsonConfigFile = 'app.json';
|
|
70
63
|
for (const jsConfigFile of jsConfigFiles) {
|
|
@@ -77,20 +70,20 @@ async function injectBinaryVersions({ versionCode, versionName, }) {
|
|
|
77
70
|
await injectToJsonConfigFile(jsonConfigFile);
|
|
78
71
|
return;
|
|
79
72
|
}
|
|
80
|
-
|
|
73
|
+
throwError('expo config file not found');
|
|
81
74
|
async function injectToJsConfigFile(filename) {
|
|
82
|
-
const filePath =
|
|
83
|
-
let content =
|
|
75
|
+
const filePath = resolve(OptionHolder.rootDir, filename);
|
|
76
|
+
let content = read(filePath);
|
|
84
77
|
content = content.replace(/const VERSION_NAME = '(.*?)';/, `const VERSION_NAME = '${versionName}';`);
|
|
85
78
|
content = content.replace(/const VERSION_CODE = (.*?);/, `const VERSION_CODE = ${versionCode};`);
|
|
86
|
-
|
|
79
|
+
write(filePath, content);
|
|
87
80
|
}
|
|
88
81
|
async function injectToJsonConfigFile(filename) {
|
|
89
|
-
const filePath =
|
|
90
|
-
const json =
|
|
82
|
+
const filePath = resolve(OptionHolder.rootDir, filename);
|
|
83
|
+
const json = readJsonSlow(filePath);
|
|
91
84
|
json.expo.version = versionName;
|
|
92
85
|
json.expo.ios.buildNumber = versionCode;
|
|
93
86
|
json.expo.android.versionCode = +versionCode;
|
|
94
|
-
|
|
87
|
+
writeJson(filePath, json);
|
|
95
88
|
}
|
|
96
89
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.calculateElapsed = calculateElapsed;
|
|
4
|
-
const js_util_1 = require("@mj-studio/js-util");
|
|
5
|
-
function calculateElapsed(t) {
|
|
1
|
+
import { padZero } from '@mj-studio/js-util';
|
|
2
|
+
export function calculateElapsed(t) {
|
|
6
3
|
let seconds = Math.floor((Date.now() - t) / 1000);
|
|
7
4
|
const minutes = Math.floor(seconds / 60);
|
|
8
5
|
seconds = seconds % 60;
|
|
9
|
-
return `${minutes}:${
|
|
6
|
+
return `${minutes}:${padZero(seconds)}`;
|
|
10
7
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const FileUtil_1 = require("./FileUtil");
|
|
6
|
-
async function hydrateKeyholderFileValues() {
|
|
7
|
-
Object.assign(OptionHolder_1.OptionHolder.keyholderFileValueMap, (0, FileUtil_1.readJsonSlow)(OptionHolder_1.OptionHolder.keyholderFilePath));
|
|
1
|
+
import { OptionHolder } from './OptionHolder';
|
|
2
|
+
import { readJsonSlow } from './FileUtil';
|
|
3
|
+
export async function hydrateKeyholderFileValues() {
|
|
4
|
+
Object.assign(OptionHolder.keyholderFileValueMap, readJsonSlow(OptionHolder.keyholderFilePath));
|
|
8
5
|
}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
async function iterateAllFilesInGeneratedTemplate(callback) {
|
|
7
|
-
for (const dir of OptionHolder_1.OptionHolder.templateDirNames) {
|
|
8
|
-
await go((0, FileUtil_1.join)(OptionHolder_1.OptionHolder.outDir, dir));
|
|
1
|
+
import { OptionHolder } from './OptionHolder';
|
|
2
|
+
import { readdir, isFile, isDir, join } from './FileUtil';
|
|
3
|
+
export async function iterateAllFilesInGeneratedTemplate(callback) {
|
|
4
|
+
for (const dir of OptionHolder.templateDirNames) {
|
|
5
|
+
await go(join(OptionHolder.outDir, dir));
|
|
9
6
|
}
|
|
10
7
|
async function go(dirPath) {
|
|
11
|
-
const paths =
|
|
8
|
+
const paths = readdir(dirPath).map((f) => join(dirPath, f));
|
|
12
9
|
for (const p of paths) {
|
|
13
|
-
if (
|
|
10
|
+
if (isFile(p)) {
|
|
14
11
|
await callback(p);
|
|
15
12
|
}
|
|
16
|
-
else if (
|
|
13
|
+
else if (isDir(p)) {
|
|
17
14
|
await go(p);
|
|
18
15
|
}
|
|
19
16
|
}
|
|
@@ -1,37 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const filePath = (0, FileUtil_1.resolve)(fastlaneSrcDir, file);
|
|
16
|
-
(0, FileUtil_1.remove)((0, FileUtil_1.resolve)(androidDir, file));
|
|
17
|
-
(0, FileUtil_1.copy)(filePath, (0, FileUtil_1.resolve)(androidDir, file));
|
|
1
|
+
import { spinner, $, path } from 'zx';
|
|
2
|
+
import { resolve, remove, iterateDir, copy, read, write } from '../FileUtil';
|
|
3
|
+
import { OptionHolder } from '../OptionHolder';
|
|
4
|
+
import { logger } from '../logger';
|
|
5
|
+
export async function prepareAndroid() {
|
|
6
|
+
const androidDir = resolve(OptionHolder.rootDir, 'android');
|
|
7
|
+
const fastlaneSrcDir = resolve(OptionHolder.outDir, 'fastlane-android');
|
|
8
|
+
const fastlaneDestDir = resolve(OptionHolder.rootDir, 'android', 'fastlane');
|
|
9
|
+
await spinner('Prebuild Android', () => $ `cd ${OptionHolder.rootDir} && expo prebuild -p android --no-install`);
|
|
10
|
+
remove(fastlaneDestDir);
|
|
11
|
+
await iterateDir(fastlaneSrcDir, async (file) => {
|
|
12
|
+
const filePath = resolve(fastlaneSrcDir, file);
|
|
13
|
+
remove(resolve(androidDir, file));
|
|
14
|
+
copy(filePath, resolve(androidDir, file));
|
|
18
15
|
});
|
|
19
|
-
|
|
16
|
+
logger.success('Inject Android Fastlane files');
|
|
20
17
|
await replaceAndroidSigningConfig();
|
|
21
18
|
async function replaceAndroidSigningConfig() {
|
|
22
|
-
const buildGradlePath =
|
|
23
|
-
const { android_keystore_store_password, android_keystore_key_alias, android_keystore_key_password, } =
|
|
24
|
-
const content =
|
|
19
|
+
const buildGradlePath = resolve(androidDir, 'app', 'build.gradle');
|
|
20
|
+
const { android_keystore_store_password, android_keystore_key_alias, android_keystore_key_password, } = OptionHolder.keyholderFileValueMap;
|
|
21
|
+
const content = read(buildGradlePath).replace(/signingConfigs.*?{.*?debug.*?{.*?}.*?}/s, `
|
|
25
22
|
signingConfigs {
|
|
26
23
|
debug {
|
|
27
|
-
storeFile file('${
|
|
24
|
+
storeFile file('${path.relative(buildGradlePath, resolve(OptionHolder.outDir, 'key', 'android_release_keystore.jks'))}')
|
|
28
25
|
storePassword '${android_keystore_store_password}'
|
|
29
26
|
keyAlias '${android_keystore_key_alias}'
|
|
30
27
|
keyPassword '${android_keystore_key_password}'
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
`);
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
write(buildGradlePath, content);
|
|
32
|
+
logger.success('Replace Android Signing Config');
|
|
36
33
|
}
|
|
37
34
|
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const filePath = (0, FileUtil_1.resolve)(fastlaneSrcDir, file);
|
|
16
|
-
(0, FileUtil_1.remove)((0, FileUtil_1.resolve)(iosDir, file));
|
|
17
|
-
(0, FileUtil_1.copy)(filePath, (0, FileUtil_1.resolve)(iosDir, file));
|
|
1
|
+
import { $, spinner } from 'zx';
|
|
2
|
+
import { remove, resolve, iterateDir, copy } from '../FileUtil';
|
|
3
|
+
import { OptionHolder } from '../OptionHolder';
|
|
4
|
+
import { logger } from '../logger';
|
|
5
|
+
export async function prepareIos() {
|
|
6
|
+
const iosDir = resolve(OptionHolder.rootDir, 'ios');
|
|
7
|
+
const fastlaneSrcDir = resolve(OptionHolder.outDir, 'fastlane-ios');
|
|
8
|
+
const fastlaneDestDir = resolve(OptionHolder.rootDir, 'ios', 'fastlane');
|
|
9
|
+
await spinner('Prebuild iOS', () => $ `cd ${OptionHolder.rootDir} && expo prebuild -p ios --no-install`);
|
|
10
|
+
remove(fastlaneDestDir);
|
|
11
|
+
await iterateDir(fastlaneSrcDir, async (file) => {
|
|
12
|
+
const filePath = resolve(fastlaneSrcDir, file);
|
|
13
|
+
remove(resolve(iosDir, file));
|
|
14
|
+
copy(filePath, resolve(iosDir, file));
|
|
18
15
|
});
|
|
19
|
-
|
|
16
|
+
logger.success('Inject iOS Fastlane files');
|
|
20
17
|
}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
OptionHolder_1.OptionHolder.rootDir = EnvUtil_1.isDev
|
|
10
|
-
? (0, FileUtil_1.resolve)('example')
|
|
11
|
-
: (0, FileUtil_1.resolve)(await (0, prompts_1.input)({
|
|
1
|
+
import { OptionHolder } from '../OptionHolder';
|
|
2
|
+
import { input } from '@inquirer/prompts';
|
|
3
|
+
import { isDev } from '../EnvUtil';
|
|
4
|
+
import { exist, resolve } from '../FileUtil';
|
|
5
|
+
export async function promptCommonInputs() {
|
|
6
|
+
OptionHolder.rootDir = isDev
|
|
7
|
+
? resolve('example')
|
|
8
|
+
: resolve(await input({
|
|
12
9
|
message: 'react native project root directory path',
|
|
13
|
-
default:
|
|
10
|
+
default: isDev ? 'example' : '.',
|
|
14
11
|
validate: (value) => {
|
|
15
|
-
const p =
|
|
16
|
-
if (!
|
|
12
|
+
const p = resolve(value, 'package.json');
|
|
13
|
+
if (!exist(p)) {
|
|
17
14
|
return "package.json hasn\'t been detected. provider valid project root.";
|
|
18
15
|
}
|
|
19
16
|
return true;
|
|
20
17
|
},
|
|
21
18
|
}));
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
OptionHolder.outDir = resolve(OptionHolder.rootDir, 'expo-local-build');
|
|
20
|
+
OptionHolder.keyDir = resolve(OptionHolder.outDir, 'key');
|
|
21
|
+
OptionHolder.keyholderFilePath = resolve(OptionHolder.outDir, 'keyholder.json');
|
|
25
22
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
await (0, promptCommonInputs_1.promptCommonInputs)();
|
|
9
|
-
await (0, hydrateKeyholderFileValues_1.hydrateKeyholderFileValues)();
|
|
10
|
-
await (0, VersionUtil_1.parseBinaryVersions)();
|
|
1
|
+
import { promptCommonInputs } from './promptCommonInputs';
|
|
2
|
+
import { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';
|
|
3
|
+
import { parseBinaryVersions } from '../VersionUtil';
|
|
4
|
+
export async function setup() {
|
|
5
|
+
await promptCommonInputs();
|
|
6
|
+
await hydrateKeyholderFileValues();
|
|
7
|
+
await parseBinaryVersions();
|
|
11
8
|
}
|
package/build/util/throwError.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.throwError = throwError;
|
|
4
|
-
const logger_1 = require("./logger");
|
|
5
|
-
function throwError(message, e) {
|
|
1
|
+
import { logger } from './logger';
|
|
2
|
+
export function throwError(message, e) {
|
|
6
3
|
if (e) {
|
|
7
|
-
|
|
4
|
+
logger.error(message, e);
|
|
8
5
|
}
|
|
9
6
|
else {
|
|
10
|
-
|
|
7
|
+
logger.error(message);
|
|
11
8
|
}
|
|
12
9
|
process.exit(1);
|
|
13
10
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-release-it",
|
|
3
3
|
"module": "src/index.ts",
|
|
4
|
-
"type": "
|
|
5
|
-
"version": "0.0.
|
|
4
|
+
"type": "module",
|
|
5
|
+
"version": "0.0.11",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"workspaces": [
|
|
36
36
|
"example"
|
|
37
37
|
],
|
|
38
|
-
"bin": "./bin/expo-release-it.
|
|
38
|
+
"bin": "./bin/expo-release-it.mjs",
|
|
39
39
|
"files": [
|
|
40
40
|
"build",
|
|
41
41
|
"package.json",
|
package/bin/expo-release-it.cjs
DELETED