expo-release-it 0.1.3 → 0.1.5
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 +205 -13
- package/build/command/build.js +68 -26
- package/build/command/build.js.map +1 -1
- package/build/command/bump.js +10 -13
- package/build/command/bump.js.map +1 -1
- package/build/command/init.js +7 -3
- package/build/command/init.js.map +1 -1
- package/build/command/pull.js +68 -25
- package/build/command/pull.js.map +1 -1
- package/build/command/submit.js +72 -30
- package/build/command/submit.js.map +1 -1
- package/build/command/upload.js +73 -31
- package/build/command/upload.js.map +1 -1
- package/build/index.js +104 -91
- package/build/index.js.map +1 -1
- package/build/util/FastlaneOption.js +4 -2
- package/build/util/FastlaneOption.js.map +1 -1
- package/build/util/MetadataSyncUtil.js +48 -19
- package/build/util/MetadataSyncUtil.js.map +1 -1
- package/build/util/OptionHolder.d.ts +1 -0
- package/build/util/OptionHolder.js +3 -1
- package/build/util/OptionHolder.js.map +1 -1
- package/build/util/generateAppStoreConnectApiKeyFile.js +4 -2
- package/build/util/generateAppStoreConnectApiKeyFile.js.map +1 -1
- package/build/util/injectTemplatePlaceHolders.js +3 -1
- package/build/util/injectTemplatePlaceHolders.js.map +1 -1
- package/build/util/input/InqueryInputs.d.ts +1 -0
- package/build/util/input/InqueryInputs.js +18 -1
- package/build/util/input/InqueryInputs.js.map +1 -1
- package/build/util/setup/VersionUtil.js +9 -11
- package/build/util/setup/VersionUtil.js.map +1 -1
- package/build/util/setup/hydrateKeyholderFileValues.js +3 -1
- package/build/util/setup/hydrateKeyholderFileValues.js.map +1 -1
- package/build/util/setup/prepareAndroid.js +25 -11
- package/build/util/setup/prepareAndroid.js.map +1 -1
- package/build/util/setup/prepareIos.js +26 -12
- package/build/util/setup/prepareIos.js.map +1 -1
- package/build/util/setup/setup.js +7 -3
- package/build/util/setup/setup.js.map +1 -1
- package/package.json +3 -1
- package/template/key/android_upload_certificate.pem +0 -2
- /package/template/key/{android_release_keystore.jks → android_release.keystore} +0 -0
- /package/template/key/{ios_testflight_upload_api_key.p8 → ios_app_store_connect_api_key.p8} +0 -0
package/README.md
CHANGED
|
@@ -2,22 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Opinionated Expo CICD workflow CLI for building & uploading & submitting Expo projects on your machine
|
|
6
6
|
|
|
7
7
|
> [!CAUTION]
|
|
8
|
-
> This project is under
|
|
8
|
+
> This project is under development.
|
|
9
9
|
|
|
10
10
|
# Features
|
|
11
11
|
|
|
12
|
-
- No EAS
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
12
|
+
- 🎉 No **EAS**
|
|
13
|
+
- 🩵 No headaches when understanding and managing **keys and credentials**
|
|
14
|
+
- 🧩 Manage and sync **store metadata** easily
|
|
15
|
+
- 🌍 Works with [Expo CNG](https://docs.expo.dev/workflow/continuous-native-generation/) mode (also available in non-CNG environments)
|
|
16
|
+
- 📦 Build artifacts **locally** (`apk`, `aab`, `ipa`)
|
|
17
|
+
- 🚀 Upload artifacts to Google Play Console Internal Testing Track and iOS TestFlight
|
|
18
|
+
- ✅ Submit releases for review
|
|
18
19
|
|
|
19
20
|
# Why?
|
|
20
21
|
|
|
22
|
+
**You don't need Expo EAS and to understand how it works in most small projects and our machine is much faster than using the cloud.**
|
|
23
|
+
|
|
24
|
+
<details>
|
|
25
|
+
<summary>Full Details</summary>
|
|
26
|
+
|
|
21
27
|
Expo EAS is convenient, but it requires additional configuration files, console setup, and a conceptual understanding of Over-The-Air (OTA) updates. Also, builds must be performed on EAS Cloud, which is not free and can be slow.
|
|
22
28
|
|
|
23
29
|
While EAS is useful for larger teams, if you are developing alone or with just a few people and question the need for such a process, `expo-release-it` is the answer.
|
|
@@ -26,42 +32,228 @@ Based on years of experience developing with React Native, I encourage a more tr
|
|
|
26
32
|
|
|
27
33
|
This approach is much faster, simpler, and, most importantly, allows you to take full advantage of your computer’s fast CPU.
|
|
28
34
|
|
|
35
|
+
OTA updates are a powerful tool in React Native, but to fully take advantage of them, you need a self-hosted CDN server, a version management console both in the cloud and inside the app, and you have to separately manage binary versions and bundle versions—all of which introduce significant complexity and semantic overhead that often outweigh the benefits of implementing OTA updates. Furthermore, due to a general lack of deep understanding about OTA updates, issues like native library version mismatches can occur frequently, so OTA updates are excluded by default.
|
|
36
|
+
|
|
37
|
+
I’m also a big fan of OTA updates, and I’ve enjoyed a lot of efficiency when working in larger teams, but it always required setting up many supporting systems in advance.
|
|
38
|
+
|
|
29
39
|
`expo-release-it` is a CLI tool that encapsulates the know-how I have gained over years of automating build and review processes.
|
|
30
40
|
Internally, it ports and integrates tools like Fastlane and Match to automate native binary builds and review requests.
|
|
31
41
|
|
|
32
42
|
Therefore, this tool enforces an opinionated versioning, build, and review request workflow.
|
|
33
43
|
However, once you understand this approach, your app deployment process will become significantly faster.
|
|
34
44
|
|
|
45
|
+
</details>
|
|
35
46
|
|
|
36
|
-
# Requirements
|
|
47
|
+
# Structurual Requirements
|
|
37
48
|
|
|
38
|
-
-
|
|
39
|
-
- All Keys, Credentials(except iOS certificates & provisioning profiles) are stored in VCS
|
|
49
|
+
- `Version Code(Android)` and `Builder Number(iOS)` are the same.
|
|
50
|
+
- All Keys, Credentials(except iOS certificates & provisioning profiles served in Github separately) are stored in VCS
|
|
40
51
|
|
|
41
52
|
# Getting Started
|
|
42
53
|
|
|
54
|
+
## 1. Ruby, Bundler
|
|
55
|
+
|
|
56
|
+
`expo-release-it` requires `bundler` of ruby is available in your environment to run `Fastlane` internally.
|
|
57
|
+
|
|
58
|
+
If not, set up your environment so that `ruby` and `bundler` are available by following [Ruby Install Guide](https://www.ruby-lang.org/en/downloads/)
|
|
59
|
+
|
|
60
|
+
## 2. Prepare Keys & Credentials
|
|
61
|
+
|
|
62
|
+
`init` command generates sample key files structure in `expo-release-it/key`. They are **noob files** and you must replace file contents.
|
|
63
|
+
|
|
64
|
+
> [!IMPORTANT]
|
|
65
|
+
**You must prepare all required key files in `expo-release-it/key` exactly the same filenames.**
|
|
66
|
+
|
|
67
|
+
### `android_play_console_service_account.json`
|
|
68
|
+
|
|
69
|
+
Google Play Console actions require authentication using Google Service Account.
|
|
70
|
+
|
|
71
|
+
You can issue new Google Play Service Account by following Guide
|
|
72
|
+
and prepare `json` file.
|
|
73
|
+
|
|
74
|
+
- [How to Get Your Google Play JSON Key](https://help.radio.co/en/articles/6232140-how-to-get-your-google-play-json-key)
|
|
75
|
+
|
|
76
|
+
### `android_release.keystore`
|
|
77
|
+
|
|
78
|
+
Prepare your android release keystore file for **uploading** and **signing** Android build artifacts.
|
|
79
|
+
|
|
80
|
+
Additional passwords, alias will be prompted during the `init` command and be stored in `keyholder.json`.
|
|
81
|
+
|
|
82
|
+
- [Keystore generation with Android Studio](https://developer.android.com/studio/publish/app-signing.html#generate-key)
|
|
83
|
+
- [Keystore generation with CLI](https://gist.github.com/henriquemenezes/70feb8fff20a19a65346e48786bedb8f)
|
|
84
|
+
|
|
85
|
+
### `ios_app_store_connect_api_key`
|
|
86
|
+
|
|
87
|
+
App Store Connect actions require authentication using App Store Connect Api Key(.p8)
|
|
88
|
+
|
|
89
|
+
Additional `issuer_id`, `key_id` values will be prompted during the `init` command and be stored in `keyholder.json`
|
|
90
|
+
|
|
91
|
+
- [Guide](https://www.revenuecat.com/docs/service-credentials/itunesconnect-app-specific-shared-secret/app-store-connect-api-key-configuration)
|
|
92
|
+
- [Apple Docs Guide](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)
|
|
93
|
+
|
|
94
|
+
## 3. Create & Configure app on the stores as much as possible
|
|
95
|
+
|
|
96
|
+
Create and configure your application in Google Play Console & App Store Connect as many as possible.
|
|
97
|
+
|
|
98
|
+
You'd have to fill your key & credentials information using `init` command and pull store metadatas using `pull` command later.
|
|
99
|
+
|
|
100
|
+
You would need to upload & publish your first artifact, release manually at first.
|
|
101
|
+
|
|
102
|
+
## 4. Set binary version in expo config file.
|
|
103
|
+
|
|
104
|
+
The following buildNumber, versionCode format `ABBBCCC` is not mandatory but recommended for readability.
|
|
105
|
+
|
|
106
|
+
If your expo config file is `app.json`, then set like the following.
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"expo": {
|
|
111
|
+
"version": "1.2.3",
|
|
112
|
+
"ios": {
|
|
113
|
+
"buildNumber": "1002003",
|
|
114
|
+
},
|
|
115
|
+
"android": {
|
|
116
|
+
"versionCode": 1002003,
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If your expo config file is `app.config.(js|ts|mjs|cjs)`, then set like the following.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import type { ExpoConfig, ConfigContext } from 'expo/config';
|
|
127
|
+
const VERSION_NAME = '1.2.3'; // VERSION_NAME variable is required.
|
|
128
|
+
const VERSION_CODE = 1002003; // VERSION_CODE variable is required.
|
|
129
|
+
|
|
130
|
+
export default ({ config }: ConfigContext): ExpoConfig => {
|
|
131
|
+
return {
|
|
132
|
+
...config,
|
|
133
|
+
version: VERSION_NAME,
|
|
134
|
+
ios: {
|
|
135
|
+
buildNumber: VERSION_CODE + '',
|
|
136
|
+
},
|
|
137
|
+
android: {
|
|
138
|
+
versionCode: VERSION_CODE,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 5. Update `.gitignore`
|
|
146
|
+
|
|
147
|
+
```gitignore
|
|
148
|
+
# Expo Release It
|
|
149
|
+
|
|
150
|
+
expo-release-it/.temp
|
|
151
|
+
android/vendor/bundle
|
|
152
|
+
ios/vendor/bundle
|
|
153
|
+
!*.jks
|
|
154
|
+
!*.p8
|
|
155
|
+
!*.keystore
|
|
156
|
+
```
|
|
43
157
|
|
|
158
|
+
## 6. Run `expo-release-it init`
|
|
44
159
|
|
|
45
160
|
# Usage
|
|
46
161
|
|
|
47
162
|
```shell
|
|
48
|
-
npx expo-release-it (init|bump|build|upload|submit) [options]
|
|
163
|
+
npx expo-release-it (init|bump|pull|build|upload|submit) [options]
|
|
49
164
|
```
|
|
50
165
|
|
|
166
|
+
All commands are powered by [Commander.js](https://github.com/tj/commander.js?) means you can query all available options with `--help` or `-h`.
|
|
167
|
+
|
|
51
168
|
## init
|
|
52
169
|
|
|
170
|
+
**Configure resources and environment**
|
|
171
|
+
|
|
172
|
+
```shell
|
|
173
|
+
npx expo-release-it init
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The `init` command asks you for many form fields, and the information is saved in `expo-release-it/keyholder.json` in your project.
|
|
177
|
+
|
|
178
|
+
Even after running `init`, you can manually edit `keyholder.json`, and all subsequent commands will use the updated values.
|
|
179
|
+
|
|
180
|
+
The resources & output directory structure is the following.
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
📁 expo-release-it/
|
|
184
|
+
├── 📁 key/ # key & certificate files
|
|
185
|
+
├── 📁 metadata/ # result of `pull`
|
|
186
|
+
│ ├── 📁 android/ # android store metadatas
|
|
187
|
+
│ └── 📁 ios/ # ios store metadatas
|
|
188
|
+
├── 📁 output/ # result of `build`
|
|
189
|
+
│ ├── 📁 android/ # android build output
|
|
190
|
+
│ └── 📁 ios/ # ios build output
|
|
191
|
+
└── keyholder.json
|
|
192
|
+
```
|
|
193
|
+
|
|
53
194
|
## bump
|
|
54
195
|
|
|
196
|
+
**Bump binary release patch version with modifying expo config file**
|
|
197
|
+
|
|
198
|
+
```shell
|
|
199
|
+
npx expo-release-it bump
|
|
200
|
+
```
|
|
201
|
+
|
|
55
202
|
## pull
|
|
56
203
|
|
|
204
|
+
**Download metadatas from stores**
|
|
205
|
+
|
|
206
|
+
```shell
|
|
207
|
+
npx expo-release-it pull
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The downloaded metadatas are stored in `expo-release-it/metadata`.
|
|
211
|
+
|
|
212
|
+
Check the following out to configure metadatas.
|
|
213
|
+
|
|
214
|
+
- [Android Metadata Manage Guide](https://docs.fastlane.tools/actions/supply/)
|
|
215
|
+
- [iOS Metadata Manage Guide](https://docs.fastlane.tools/actions/deliver/)
|
|
216
|
+
|
|
217
|
+
|
|
57
218
|
## build
|
|
58
219
|
|
|
220
|
+
**Build artifacts (apk, aab, ipa)**
|
|
221
|
+
|
|
222
|
+
```shell
|
|
223
|
+
npx expo-release-it build
|
|
224
|
+
```
|
|
225
|
+
|
|
59
226
|
## upload
|
|
60
227
|
|
|
228
|
+
**Upload artifact to play console internal test track(android) and testflight(ios)**
|
|
229
|
+
|
|
230
|
+
```shell
|
|
231
|
+
npx expo-release-it upload
|
|
232
|
+
```
|
|
233
|
+
|
|
61
234
|
## submit
|
|
62
235
|
|
|
63
|
-
|
|
236
|
+
**Submit Google Play Console & App Store Connect Review with latest testing track**
|
|
237
|
+
|
|
238
|
+
```shell
|
|
239
|
+
npx expo-release-it submit
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
# About Security
|
|
243
|
+
|
|
244
|
+
That’s right. You might be wondering whether storing files like .p8, keystore files, or key values in version control is truly secure.
|
|
245
|
+
In conclusion, if you’re using a private repository, you can consider it to be somewhat safe.
|
|
246
|
+
|
|
247
|
+
For example, Fastlane Match also uses OpenSSL encryption, but it still stores certificates and profiles in a private Git repository.
|
|
248
|
+
|
|
249
|
+
While you could implement additional security policies, I haven’t taken any extra measures for now.
|
|
250
|
+
If you need further encryption, you can build middleware in your pipeline that runs expo-release-it so that everything in the expo-release-it directory goes through encryption and decryption processes.
|
|
251
|
+
|
|
252
|
+
Any suggestions are welcome.
|
|
253
|
+
|
|
254
|
+
# Troubleshooting
|
|
64
255
|
|
|
256
|
+
# Licenses
|
|
65
257
|
|
|
66
258
|
- See [LICENSE](/LICENSE)
|
|
67
259
|
|
package/build/command/build.js
CHANGED
|
@@ -58,8 +58,10 @@ var package_default = {
|
|
|
58
58
|
name: "expo-release-it",
|
|
59
59
|
module: "src/index.ts",
|
|
60
60
|
type: "module",
|
|
61
|
-
version: "0.1.
|
|
61
|
+
version: "0.1.4",
|
|
62
62
|
license: "MIT",
|
|
63
|
+
homepage: "https://github.com/mym0404/expo-release-it",
|
|
64
|
+
repository: "https://github.com/mym0404/expo-release-it",
|
|
63
65
|
scripts: {
|
|
64
66
|
build: "tsup",
|
|
65
67
|
dev: "yarn run build && NODE_ENV=development node bin/expo-release-it.mjs",
|
|
@@ -199,17 +201,29 @@ function copyIosMetadata(to) {
|
|
|
199
201
|
const metadataResourcesDir = join2(resourcesDir, "metadata");
|
|
200
202
|
const screenshotsResourcesDir = join2(resourcesDir, "screenshots");
|
|
201
203
|
if (to === "resources") {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
if (exist(metadataNativeDir) && exist(screenshotsNativeDir)) {
|
|
205
|
+
copy(metadataNativeDir, metadataResourcesDir);
|
|
206
|
+
copy(screenshotsNativeDir, screenshotsResourcesDir);
|
|
207
|
+
logger.done(
|
|
208
|
+
`iOS Metadata saved in ${chalk3.inverse(relativePath(OptionHolder.projectDir, resourcesDir))}. You can edit inside contents.`
|
|
209
|
+
);
|
|
210
|
+
} else {
|
|
211
|
+
logger.warn(
|
|
212
|
+
`iOS Metadata not found in ${chalk3.inverse(relativePath(OptionHolder.projectDir, nativeDir))}`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
207
215
|
} else {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
if (exist(metadataResourcesDir) && exist(screenshotsResourcesDir)) {
|
|
217
|
+
copy(metadataResourcesDir, metadataNativeDir);
|
|
218
|
+
copy(screenshotsResourcesDir, screenshotsNativeDir);
|
|
219
|
+
logger.done(
|
|
220
|
+
`iOS Metadata copyed to ${chalk3.inverse(relativePath(OptionHolder.projectDir, nativeDir))}`
|
|
221
|
+
);
|
|
222
|
+
} else {
|
|
223
|
+
logger.warn(
|
|
224
|
+
`iOS Metadata not found in ${chalk3.inverse(relativePath(OptionHolder.projectDir, resourcesDir))}`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
213
227
|
}
|
|
214
228
|
}
|
|
215
229
|
function copyAndroidMetadata(to) {
|
|
@@ -217,15 +231,27 @@ function copyAndroidMetadata(to) {
|
|
|
217
231
|
const nativeDir = join2(androidDir, "fastlane/metadata/android");
|
|
218
232
|
const resourcesDir = join2(OptionHolder.resourcesDir, "metadata/android");
|
|
219
233
|
if (to === "resouces") {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
234
|
+
if (exist(nativeDir)) {
|
|
235
|
+
copy(nativeDir, resourcesDir);
|
|
236
|
+
logger.done(
|
|
237
|
+
`Android Metadata saved in ${chalk3.inverse(relativePath(OptionHolder.projectDir, resourcesDir))}. You can edit inside contents.`
|
|
238
|
+
);
|
|
239
|
+
} else {
|
|
240
|
+
logger.warn(
|
|
241
|
+
`Android Metadata not found in ${chalk3.inverse(relativePath(OptionHolder.projectDir, nativeDir))}`
|
|
242
|
+
);
|
|
243
|
+
}
|
|
224
244
|
} else {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
245
|
+
if (exist(resourcesDir)) {
|
|
246
|
+
copy(resourcesDir, nativeDir);
|
|
247
|
+
logger.done(
|
|
248
|
+
`Android Metadata copyed to ${chalk3.inverse(relativePath(OptionHolder.projectDir, nativeDir))}`
|
|
249
|
+
);
|
|
250
|
+
} else {
|
|
251
|
+
logger.warn(
|
|
252
|
+
`Android Metadata not found in ${chalk3.inverse(relativePath(OptionHolder.projectDir, resourcesDir))}`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
229
255
|
}
|
|
230
256
|
}
|
|
231
257
|
|
|
@@ -250,7 +276,7 @@ async function prepareAndroid() {
|
|
|
250
276
|
"Hydrate template placeholders",
|
|
251
277
|
injectTemplatePlaceHolders(resolve2(destDir, "fastlane"))
|
|
252
278
|
);
|
|
253
|
-
await exe({ cwd: destDir })
|
|
279
|
+
await exe("bundle", ["install"], { cwd: destDir });
|
|
254
280
|
logger.success("Bunder Install - Done");
|
|
255
281
|
copyAndroidMetadata("native");
|
|
256
282
|
}
|
|
@@ -267,7 +293,7 @@ async function replaceAndroidSigningConfig(destDir) {
|
|
|
267
293
|
`
|
|
268
294
|
signingConfigs {
|
|
269
295
|
debug {
|
|
270
|
-
storeFile file('${relativePath(buildGradleDirPath, resolve2(OptionHolder.resourcesDir, "key", "
|
|
296
|
+
storeFile file('${relativePath(buildGradleDirPath, resolve2(OptionHolder.resourcesDir, "key", "android_release.keystore"))}')
|
|
271
297
|
storePassword '${android_keystore_store_password}'
|
|
272
298
|
keyAlias '${android_keystore_key_alias}'
|
|
273
299
|
keyPassword '${android_keystore_key_password}'
|
|
@@ -297,6 +323,8 @@ function throwError(message, e) {
|
|
|
297
323
|
|
|
298
324
|
// src/util/setup/VersionUtil.ts
|
|
299
325
|
import semver from "semver";
|
|
326
|
+
var versionNameRegex = () => /const\s+VERSION_NAME\s*?=\s*?['"]([\d\.]*?)['"]\s*?;?/;
|
|
327
|
+
var versionCodeRegex = () => /const\s+VERSION_CODE\s*?=\s*?(\d+)\s*?;?/;
|
|
300
328
|
async function parseBinaryVersions() {
|
|
301
329
|
const files = readdir(OptionHolder.projectDir);
|
|
302
330
|
const jsConfigFiles = ["app.config.ts", "app.config.js", "app.config.cjs", "app.config.mjs"];
|
|
@@ -315,8 +343,8 @@ async function parseBinaryVersions() {
|
|
|
315
343
|
async function parseFromJsConfigFile(filename) {
|
|
316
344
|
const filePath = resolve2(OptionHolder.projectDir, filename);
|
|
317
345
|
const content = read(filePath);
|
|
318
|
-
const VERSION_NAME =
|
|
319
|
-
const VERSION_CODE =
|
|
346
|
+
const VERSION_NAME = versionNameRegex().exec(content)?.[1];
|
|
347
|
+
const VERSION_CODE = versionCodeRegex().exec(content)?.[1];
|
|
320
348
|
if (!VERSION_NAME) {
|
|
321
349
|
throwError("cannot parse version name");
|
|
322
350
|
}
|
|
@@ -390,7 +418,7 @@ async function prepareIos() {
|
|
|
390
418
|
"Hydrate template placeholders",
|
|
391
419
|
injectTemplatePlaceHolders(resolve2(destDir, "fastlane"))
|
|
392
420
|
);
|
|
393
|
-
await exe({ cwd: destDir })
|
|
421
|
+
await exe("bundle", ["install"], { cwd: destDir });
|
|
394
422
|
logger.success("Bunder Install - Done");
|
|
395
423
|
copyIosMetadata("native");
|
|
396
424
|
}
|
|
@@ -426,6 +454,21 @@ var InqueryInputs = {
|
|
|
426
454
|
});
|
|
427
455
|
}
|
|
428
456
|
},
|
|
457
|
+
platformAll: async () => {
|
|
458
|
+
if (!OptionHolder.input.platformAll) {
|
|
459
|
+
OptionHolder.input.platformAll = await select({
|
|
460
|
+
message: constructInquirerFormattedMessage({
|
|
461
|
+
name: "Platform",
|
|
462
|
+
explanation: `Platforms to run action`
|
|
463
|
+
}),
|
|
464
|
+
choices: [
|
|
465
|
+
{ name: "all", value: "all", description: "Both" },
|
|
466
|
+
{ name: "ios", value: "ios", description: "Release ios" },
|
|
467
|
+
{ name: "android", value: "android", description: "Release android" }
|
|
468
|
+
]
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
},
|
|
429
472
|
podinstall: async () => {
|
|
430
473
|
if (OptionHolder.input.platform === "ios") {
|
|
431
474
|
OptionHolder.input.pod = await select({
|
|
@@ -503,7 +546,7 @@ function getIosFastlaneOptions() {
|
|
|
503
546
|
...Object.entries(OptionHolder.keyholderMap).map(([k, v]) => `${k}:${v}`),
|
|
504
547
|
`version_name:${OptionHolder.versionName}`,
|
|
505
548
|
`version_code:${OptionHolder.versionCode}`,
|
|
506
|
-
`api_key_filepath:${resolve2(OptionHolder.keyDir, "
|
|
549
|
+
`api_key_filepath:${resolve2(OptionHolder.keyDir, "ios_app_store_connect_api_key.p8")}`,
|
|
507
550
|
`upload_metadata:${OptionHolder.input.uploadMetadata}`,
|
|
508
551
|
`ipa_path:${resolve2(OptionHolder.resourcesDir, "output", "ios", "app.ipa")}`,
|
|
509
552
|
`ipa_dir:${resolve2(OptionHolder.resourcesDir, "output", "ios")}`,
|
|
@@ -518,7 +561,6 @@ async function build({ options }) {
|
|
|
518
561
|
await setup();
|
|
519
562
|
await promptInputs();
|
|
520
563
|
logger.info("Build Started");
|
|
521
|
-
logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
|
|
522
564
|
if (OptionHolder.input.platform === "ios") {
|
|
523
565
|
await buildIos();
|
|
524
566
|
logger.success(`iOS Build ${chalk5.bold.inverse(calculateElapsed(startTime))}`);
|