Compare commits

...
Author SHA1 Message Date
cruzach 0fc811b8cc [ios] update shell app to have custom config files 2020-03-18 10:34:16 -04:00
cruzach 890e45612a push /build folder 2020-03-17 13:50:37 -04:00
cruzach fec4914c8d [ios][android] add shell apps with helpshift and config files 2020-03-16 13:56:52 -04:00
cruzach 8ce26bfdb2 add SDK 36 ios shell app with helpshift 2020-03-14 10:50:16 -04:00
Dominik Sokal 941a605591 [turtle-cli] print currently using java version (if other than 8) 2020-03-10 12:26:28 +01:00
Dominik Sokal 8b9ad9846b [turtle-cli] replace / with __ to fix a bug with selecting APK file in Android Studio 2020-03-10 10:46:23 +01:00
Charlie Cruzan d488177daa Update CHANGELOG.md 2020-03-09 14:47:59 -04:00
cruzach 1ef3564adf Release 0.13.10 2020-03-09 14:44:58 -04:00
Dominik Sokal 1e29177bd0 preinstall gradle 4.10.2 and 5.6.3 (#189) 2020-03-09 13:56:02 +01:00
cruzach aa1605a5db [ios][expo-ads-admob][expo-ads-facebook] Remove UIWebView refs 2020-03-08 11:18:27 -04:00
Dominik Sokal 2f628efda3 Upgrade NDK to 17c (#188)
* upgrade ndk

* fix Dockerfile

* update CHANGELOG
2020-03-06 12:06:52 +01:00
Dominik Sokal 7f95b533ad [turtle-cli] verify if --public-url is a https url 2020-03-05 12:44:54 +01:00
Dominik Sokal 478d9ebe2b Update CHANGELOG.md 2020-03-05 09:51:04 +01:00
cruzach 0d1366b180 [ios] remove UIWebView 2020-03-03 08:25:21 -08:00
Dominik Sokal 8615f2eb9b [turtle-cli] fix platform for logs when using shortcut commands 2020-03-03 11:06:43 +01:00
Dominik Sokal a3b7867f10 volta: pin [email protected] 2020-03-03 10:53:12 +01:00
Dominik Sokal 656c53dde6 add .history to .gitignore 2020-03-02 10:32:57 +01:00
Eric Samelson e1fed149be update CHANGELOG 2020-02-13 12:27:46 -08:00
Eric Samelson 752b767800 Release 0.13.9 2020-02-13 12:26:14 -08:00
Eric Samelson 4b2ff4fced [ios] fix Notifications.getDevicePushTokenAsync occasional errors 2020-02-13 12:04:49 -08:00
Dominik Sokal a6501db230 install jq on android builder (#178) 2020-02-04 12:53:33 +01:00
cruzach 73e249854a Update Changelog 2020-01-27 18:42:10 -05:00
cruzach 1fb5d448fb Release 0.13.8 2020-01-27 18:22:09 -05:00
cruzach f1e1ef782b [android] prevent apps from crashing on startup 2020-01-27 15:09:30 -05:00
cruzach 81c905ed95 [android] add MapsPackage handling for mapview 2020-01-27 11:21:21 -05:00
Dominik Sokal ecdc8486fe Release 0.13.7 2020-01-17 12:22:50 +01:00
Quinlan Jung 6adaaf5dd1 bump traveling-fastlane to 1.11.4 (#172)
* bump traveling-fastlane to 1.11.4

* its not 2029 yet
2020-01-17 12:10:18 +01:00
Dominik Sokal 57c7dbfb43 fix ios smoke tests (#173)
* fix ios smoke tests

* download sdk35 instead of sdk32
2020-01-17 12:09:27 +01:00
dependabot[bot] cee42b1d6c Bump handlebars from 4.1.0 to 4.5.3 (#171)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.0 to 4.5.3.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...v4.5.3)

Signed-off-by: dependabot[bot] <[email protected]>
2020-01-02 10:20:48 +01:00
Tomasz Sapeta 69905bd886 Release 0.13.6 2019-12-17 20:30:04 +01:00
Tomasz Sapeta 37a8cff615 Update changelog 2019-12-17 20:29:36 +01:00
Wojciech Kozyra c8992aa2f4 Release 0.13.5 2019-12-17 16:28:00 +01:00
Tomasz Sapeta 38e05bc20a Add missing RCTAssetsLibraryRequestHandler to iOS tarball for SDK36 (#170)
### Motivation and Context

Fixes https://github.com/expo/expo/issues/6524

### Description

Updating iOS shell tarball for SDK36.
2019-12-17 16:25:22 +01:00
Dominik Sokal 4a8e14fa8b Release 0.13.4 2019-12-13 10:15:37 +01:00
Dominik Sokal 77c7fce666 upgrade @expo/xdl to 57.4.0 2019-12-13 10:10:29 +01:00
Eric Samelson 7f6faecbd1 Release 0.13.3 2019-12-12 13:47:48 -08:00
Eric Samelson 718e3e9ab6 update CHANGELOG 2019-12-12 13:45:57 -08:00
Eric Samelson 2a120fa22c [ios] remove private API usage from SDK 36 tarball 2019-12-12 13:45:14 -08:00
Eric Samelson 1b6e482be5 Release 0.13.2 2019-12-10 21:47:03 -08:00
Eric Samelson 5072a98b50 update CHANGELOG 2019-12-10 21:46:45 -08:00
Eric Samelson 0584fd20fb [android] fix deps in SDK 36 tarball 2019-12-10 19:05:15 -08:00
Eric Samelson 701d6afcf7 [android] update SDK 36 shell tarball with rootview background color fix 2019-12-10 17:36:30 -08:00
Eric Samelson 87515eae23 bump xdl to 57.3.1 2019-12-10 17:32:51 -08:00
Brent Vatne 27de1abc09 Bump xdl (#167) 2019-12-10 14:18:59 -08:00
Eric Samelson f5fb3ae4b6 Release 0.13.1 2019-12-09 14:51:01 -08:00
Eric Samelson 9a4f97c4ed update CHANGELOG 2019-12-09 14:50:51 -08:00
Eric Samelson 1bbcd8f0cc [android] fix SDK 36 tarball 2019-12-09 14:38:39 -08:00
Eric Samelson 415f0dd2aa Release 0.13.0 2019-12-09 12:37:46 -08:00
Eric Samelson 86766ddfef update CHANGELOG 2019-12-09 12:37:31 -08:00
Eric Samelson e976e86607 [ios][android] add SDK 36 tarballs (#165) 2019-12-09 12:35:16 -08:00
Dominik Sokal 6399d64033 Release 0.12.12 2019-11-22 12:16:00 +01:00
Dominik Sokal 3d8dc3cab8 Fix expo.owner not being used (#163)
* [turtle-cli] use expo.owner if defined

* update CHANGELOG
2019-11-22 12:14:30 +01:00
Quinlan Jung ae1a6e8820 Release 0.12.11 2019-11-20 15:24:08 -08:00
Quinlan Jung 52eb27c7b8 Update CHANGELOG 2019-11-20 15:22:17 -08:00
Quinlan Jung 4b9d90544a bump traveling-fastlane to 1.11.0 2019-11-20 15:21:33 -08:00
Quinlan Jung 7871bb039a Release 0.12.10 2019-11-15 14:59:27 -08:00
Quinlan Jung 507102dfac Update CHANGELOG 2019-11-15 14:56:54 -08:00
Quinlan Jung d6dd722d8b add shellAppSdkVersion param to iosShellAppBuilder (#162) 2019-11-15 14:52:11 -08:00
Dominik Sokal b2aed931b5 Release 0.12.9 2019-11-14 10:26:07 +01:00
Dominik Sokal 4e6ffc1235 update CHANGELOG 2019-11-14 10:24:15 +01:00
Dominik Sokal 811cc433ca add updating turtle and supported sdk versions in www (#161) 2019-11-13 12:43:13 +01:00
Dominik Sokal 52cbd973b3 remove extra empty line 2019-11-04 09:43:06 +01:00
Stanisław Chmiela 397bd15203 Upgrade XDL to support Facebook autoinit-disabling features (#155)
* Upgrade XDL to support Facebook autoinit-disabling features

* Add changelog entry

* To Be Reverted: update SDK35 tarball with temporary Expo-master with required changes

* To Be Reverted: update SDK35 tarball with temporary Expo-master with required changes

* Revert "To Be Reverted: update SDK35 tarball with temporary Expo-master with required changes"

This reverts commit e9ca00faf3.

* Revert "To Be Reverted: update SDK35 tarball with temporary Expo-master with required changes"

This reverts commit beafc10133.
2019-10-30 18:24:25 +01:00
cruzach 1f6f6f7caf update CHANGELOG 2019-10-29 15:35:47 -04:00
cruzach 0e7b0633d5 Release 0.12.8 2019-10-29 15:31:37 -04:00
cruzach 2b890be48e [android] update SDK 35 shell tarball to fix Linking.openUrl 2019-10-29 13:45:14 -04:00
Dominik Sokal fac39ba644 [turtle-cli] enforce java 8 (#156)
* [turtle-cli] enforce java 8

* update CHANGELOG
2019-10-28 11:38:28 +01:00
Eric Samelson a28f407f03 update CHANGELOG 2019-10-25 12:15:01 -07:00
Eric Samelson eee18d2f18 Release 0.12.7 2019-10-25 12:13:22 -07:00
Eric Samelson 6457adba57 [android] update SDK 35 shell tarball to fix GCM crash 2019-10-25 12:13:08 -07:00
Eric Samelson 6ad71bd512 Release 0.12.6 2019-10-25 12:11:48 -07:00
Dominik Sokal 0ee897531f handle invalid build jobs in better way (#152) 2019-10-24 12:43:57 +02:00
cruzach 8c46d1c8bf update CHANGELOG 2019-10-18 19:34:26 -04:00
cruzach d87873637b Release 0.12.5 2019-10-18 19:20:37 -04:00
cruzach d6496996b6 update SDK 35 shell tarball with WebBrowser fix 2019-10-18 15:37:08 -04:00
Eric Samelson 2df39da2e6 Release 0.12.4 2019-10-11 16:08:23 -07:00
Eric Samelson 6925e290cc Update CHANGELOG 2019-10-11 16:08:14 -07:00
Eric Samelson 9e2557b6f4 [android] update SDK 35 shell tarball with OTA update fix 2019-10-11 14:45:51 -07:00
Quinlan Jung d743f8313e Release 0.12.3 2019-10-09 15:02:48 -07:00
Quinlan Jung 7df3f70e9c Update CHANGELOG 2019-10-09 14:52:26 -07:00
Quinlan Jung 34cf811fd7 update client shell tarball (#145) 2019-10-08 09:58:23 -07:00
Eric Samelson 1d825e6310 Release 0.12.2 2019-09-27 10:14:48 -07:00
Eric Samelson dd6c806e0f Update CHANGELOG 2019-09-27 10:14:36 -07:00
Eric Samelson ccbdf7418e [android] update sdk35 shell tarball with battery fix 2019-09-26 22:20:58 -07:00
Eric Samelson 552c1074c0 Release 0.12.1 2019-09-20 16:35:45 -07:00
Eric Samelson 18d35d7730 Update CHANGELOG 2019-09-20 16:35:21 -07:00
Eric Samelson 7aaac7b648 [ios] update sdk 35 shell app with notification token cleanup 2019-09-20 16:34:58 -07:00
Eric Samelson c472a5a6ea [ios] backport ios 13 fixes to SDK 33 and 34 2019-09-20 15:43:41 -07:00
Eric Samelson 527821ee50 Release 0.12.0 2019-09-19 15:02:17 -07:00
Eric Samelson d2bff1639c Update CHANGELOG 2019-09-19 15:00:25 -07:00
Eric Samelson 84cf930537 [ios][android] add sdk35 and remove sdk27-30 shell tarballs (#140) 2019-09-19 14:40:17 -07:00
Stanisław Chmiela 4c3582b8df [changelog] Update changelog entry 2019-09-19 07:24:46 +02:00
Stanisław Chmiela 52b029a5a9 Release 0.11.3 2019-09-19 07:23:32 +02:00
Stanisław Chmiela 86047db677 [expo-branch] Change package of vendored expo-branch (#138)
* [expo-branch] Change package of vendored expo-branch

* shell tarball with rebuilt expokit

* Update SDK34 Android tarball
2019-09-19 07:21:55 +02:00
Wojciech Kozyra 2b8548f489 Update CHANGELOG 2019-08-21 12:29:13 +02:00
Wojciech Kozyra 44b0d8c696 Release 0.11.2 2019-08-21 12:28:01 +02:00
Wojciech Kozyra 9b70b047a3 Support for GoogleService-Info.plist (>=34.0.0) (#132) 2019-08-21 12:21:24 +02:00
Eric Samelson 98310af75a update CHANGELOG with missed fixes for 0.9.0 2019-08-12 11:49:06 -07:00
Stanisław Chmiela 5f9bf0e735 Update CHANGELOG after publishing 0.11.1 2019-08-08 09:28:59 +02:00
Stanisław Chmiela 32c8032bb3 Release 0.11.1 2019-08-08 09:28:04 +02:00
Stanisław Chmiela 10322bbca1 Update iOS client shell app (with fixes up to 2.12.3) 2019-08-08 09:27:32 +02:00
Stanisław Chmiela 88ca49766a Update CHANGELOG 2019-08-07 15:04:20 +02:00
Stanisław Chmiela 0d22f3ed0f Release 0.11.0 2019-08-07 15:00:19 +02:00
Stanisław Chmiela 32d104a03b Make only expo-branch an optional unimodule (always add expo-face-detector to standalone apps) 2019-08-07 14:50:07 +02:00
Stanisław ChmielaandDominik Sokal 97422aeb54 Update SDK34 Android tarball (#128)
* Update SDK34 Android tarball

* Update changelog

* Update iOS shell tarball

* Fix wording in changelog

Co-Authored-By: Dominik Sokal <[email protected]>

* Add missing point at the end of a sentence
2019-08-07 14:28:05 +02:00
Wojciech Kozyra 7a80d92e72 require explicit opt in for certain unimodules (#127)
- expo-branch
- expo-face-detector
2019-08-02 10:17:42 +02:00
Eric Samelson 1a2a7654c2 Release 0.10.0 2019-08-01 15:37:02 -07:00
Eric Samelson a5aaa46790 update CHANGELOG 2019-08-01 15:35:50 -07:00
Dominik Sokal 1691655f61 Update CHANGELOG.md 2019-08-01 09:54:45 +02:00
Eric Samelson f38ab7c9ee [android] fix sdk 34 tarball 2019-07-31 17:52:10 -07:00
Eric Samelson 8fd8a6e70e [ios] update SDK 33 and 34 shell apps with scoped permissions fix 2019-07-31 14:03:11 -07:00
Eric Samelson 43a319b12b [android] update SDK 34 shell app to 2.12.1 2019-07-31 12:35:00 -07:00
Eric Samelson 511f58e6ec [android] fully disable optional modules for now 2019-07-31 11:44:51 -07:00
Dominik Sokal 350f68e330 make docker image builds faster (#125)
* make docker image builds faster

* Update docker-base/Dockerfile
2019-07-31 13:41:00 +02:00
Dominik Sokal 851b0a62ab Release 0.9.1 2019-07-29 16:30:57 +02:00
Dominik Sokal d97f290ce1 update CHANGELOG 2019-07-29 16:30:35 +02:00
Dominik Sokal 2feb10aeec update release-it to 12.3.4 2019-07-29 16:28:00 +02:00
Dominik Sokal 8a288c271a Release 0.9.0 2019-07-29 16:03:27 +02:00
Dominik Sokal 47fe68abbd update CHANGELOG 2019-07-29 16:02:59 +02:00
Stanisław Chmiela 51d00a8706 [sdk34] Add shell tarballs for iOS (#124)
* [ios] Add iOS shell app tarball

* [ios] Update shell tarball for Expo client

* Add changelog entry

* update expo client shell app
2019-07-29 15:58:37 +02:00
Dominik Sokal 3f25edccd7 Update CONTRIBUTING.md 2019-07-26 14:52:40 +02:00
Dominik Sokal 2f10ab1bc9 fix passing android config to builder (#123)
* fix passing android config to builder

* update CHANGELOG
2019-07-26 14:51:27 +02:00
Dominik Sokal 4f8c21a075 add xcode license check (#121) 2019-07-26 11:49:03 +02:00
Dominik Sokal 7179f6019c fix ios archive builds (#120) 2019-07-26 11:14:37 +02:00
Bartłomiej Bukowski 2bbf2d7784 [android][sdk34] Add shellapp tarball for Android SDK34 standalone apps
* [sdk34] Add tarball for Android SDK34 with shell app

* [sdk34] Add tarball for iOS SDK34 with shell app

* [sdk34][android] Update tarball

* [sdk34][android] Update tarball

* [sdk34][android] Update tarball

* Remove invalid SDK34 iOS shellapp tarball URL

* Add changelog entry
2019-07-26 08:50:56 +02:00
Eric Samelson 3ccb4c994e update iOS shell tarballs for SDK 31, 32, and 33 with iOS 13 crash fix 2019-07-25 16:18:12 -07:00
Dominik Sokal 46706a7cdb upgrade @expo/xdl to 56.1.4-rc.0 (fixes Android constants bug) 2019-07-25 10:40:54 +02:00
Dominik Sokal 383358b11d automate turtle-cli updates in the turtle-cli-example repo (#119) 2019-07-24 11:31:26 +02:00
Dominik Sokal a87cc75b5d Release 0.8.11 2019-07-23 17:08:34 +02:00
Dominik Sokal 391a3a9937 fix android debug builds (#118) 2019-07-23 15:10:18 +02:00
Dominik Sokal 7cfedbc448 Release 0.8.10 2019-07-16 13:01:26 +02:00
Dominik Sokal 9b6eb8b66a update CHANGELOG 2019-07-16 12:59:10 +02:00
Dominik Sokal c52a126409 fix ios simulator 2019-07-16 11:14:37 +02:00
Dominik Sokal 908ab0f74d updated CHANGELOG 2019-07-15 12:29:22 +02:00
Dominik Sokal ab15d4c407 Release 0.8.9 2019-07-15 12:28:10 +02:00
Dominik Sokal 9f7b77a09c fixed user authentication 2019-07-15 12:27:13 +02:00
Dominik Sokal 67260647ff [gh issue template] feature-request -> enhancement 2019-07-12 16:27:40 +02:00
Dominik Sokal 849759c6c5 add github issue templates; update existing pull request template (#113) 2019-07-12 16:26:01 +02:00
Dominik Sokal fdcf67c96f Release 0.8.8 2019-07-11 17:03:17 +02:00
Dominik Sokal 407db0efb6 upgraded @expo/xdl to fix TouchID on iOS 2019-07-11 16:57:00 +02:00
Wojciech Kozyra 8ec619a627 Release 0.8.7 2019-07-05 11:22:56 +02:00
Wojciech Kozyra 849e026833 [android] Update shell tarball for SDK33 with 64 bit builds (#110) 2019-07-05 11:22:19 +02:00
Dominik Sokal 13652b0e07 clean up repository from redundant scripts (#109) 2019-07-05 09:44:38 +02:00
Dominik Sokal 06c2c71515 add circleci jobs for turtle deployment (#105)
* add circleci jobs for turtle deployment

* add checkout step

* remove redundant npm scripts

* remove docker:* and deploy:android npm scripts

* improve docs and remove duplicated scripts
2019-07-04 08:44:09 +02:00
Quinlan Jung 5f98e9f5ce schema change (#108)
* schema change

* debug msg
2019-07-02 10:49:48 +02:00
Quinlan Jung f314ef17dd bump traveling fastlane (#107) 2019-07-02 10:41:09 +02:00
Quinlan Jung 30274bfd7e [turtle] use provisioiningProfileId if specified (#88)
* [turtle] use provisioiningProfileId if specified

* make ts happy

* update changelog
2019-07-01 13:21:51 -07:00
Dominik Sokal 8ef99f2eae remove redundant import 2019-06-27 13:03:51 +02:00
Dominik Sokal 855e4bb962 send turtle metadata to different redis 2019-06-27 12:53:30 +02:00
Dominik Sokal df789b2de7 add registering supported sdk versions in redis (#103) 2019-06-25 17:22:36 +02:00
Wojciech Kozyra eff0556291 Update CHANGELOG.md 2019-06-25 17:06:07 +02:00
Wojciech Kozyra db74843ae0 Release 0.8.6 2019-06-25 17:05:13 +02:00
Wojciech KozyraandDominik Sokal a0e1382531 update xdl (fix support for binary plist) (#101)
* update xdl (fix support for binary plist)

* Update CHANGELOG.md

* Apply suggestions from code review

Co-Authored-By: Dominik Sokal <[email protected]>
2019-06-25 16:33:15 +02:00
Wojciech Kozyra 952dcd0cd3 fix schema for android buildModes(ts error) 2019-06-19 17:16:35 +02:00
Wojciech Kozyra 0cd4e2953a fix schema for android buildModes 2019-06-19 16:42:48 +02:00
Wojciech Kozyra a03d93cb27 Revert "Release 0.8.5"
This reverts commit 75316b5f07.
2019-06-19 16:42:01 +02:00
Wojciech Kozyra 010e92472b Update CHANGELOG.md 2019-06-19 16:11:18 +02:00
Wojciech Kozyra 75316b5f07 Release 0.8.5 2019-06-19 16:07:40 +02:00
Stanisław Chmiela 4baa49e8fe [android] Support buildMode = debug | release (#99)
* [android] Support buildMode = debug | release

* Upgrade XDL to include buildMode feature
2019-06-19 16:05:17 +02:00
Nick Novitski edb167e6b1 xdl: 54.1.4 -> 55.0.0 (#98) 2019-06-18 10:03:49 +02:00
Stanisław Chmiela d552b97654 [android] Update SDK33 tarball to update Lottie dependency (#97)
Fixes https://github.com/expo/expo/issues/4510 on Turtle
2019-06-17 17:50:46 +02:00
Wojciech Kozyra 12718c0b36 redirect logs to superivsord (#96) 2019-06-17 13:52:03 +02:00
Dominik Sokal f9600f26e8 fix error serialization 2019-06-17 13:36:34 +02:00
Dominik Sokal 68f9744f7b update CHANGELOG 2019-06-14 15:09:23 +02:00
Dominik Sokal 8c2031c3d7 [turtle-cli] don't require gulp-cli installed globally 2019-06-14 15:09:23 +02:00
Dominik Sokal 3165b5346e [turtle-cli] fix updating shell apps (#95) 2019-06-14 10:53:44 +02:00
Dominik Sokal 1552c9e7f2 Release 0.8.4 2019-06-13 16:15:50 +02:00
Dominik Sokal 51a0e772c0 upgraded sharp to 0.22.1 2019-06-13 15:49:35 +02:00
Wojciech Kozyra 98747c1db6 fix eventlistener in supervisord 2019-06-13 13:16:38 +02:00
Dominik Sokal 4f64aa2617 log build priority 2019-06-13 11:33:42 +02:00
Wojciech Kozyra 1f487d39fb update CHANGELOG.md 2019-06-13 11:23:56 +02:00
Wojciech Kozyra f7e647c1f4 Release 0.8.3 2019-06-13 11:22:34 +02:00
Dominik Sokal d900e3c491 unify installing android sdk (in docker and with turtle-cli) (#94) 2019-06-13 11:19:41 +02:00
Wojciech KozyraandDominik Sokal 32b049df86 add supervisord (#93)
* add supervisord

- restart pod only if there is at least 5 failures in 10 minutes

* Update CHANGELOG.md

Co-Authored-By: Dominik Sokal <[email protected]>

* Update scripts/android/supervisordEventListener.sh

Co-Authored-By: Dominik Sokal <[email protected]>
2019-06-13 10:53:30 +02:00
Wojciech Kozyra 723c84b575 update CHANGELOG 2019-06-13 10:47:49 +02:00
Wojciech KozyraandDominik Sokal 0ab4d2ed90 fetch manifest in turtle-cli (#91)
* fetch manifest in turtle-cli

* Update CHANGELOG.md

Co-Authored-By: Dominik Sokal <[email protected]>
2019-06-12 13:21:53 +02:00
265 changed files with 7600 additions and 2693 deletions

No files matched your search

+69 -2
View File
@@ -137,6 +137,23 @@ commands:
paths:
- "<< parameters.workingdir >>/<< parameters.platform >>/<< parameters.sdk_version >>"
deploy_turtle:
parameters:
platform:
type: string
env:
type: string
steps:
- checkout
- run:
name: Install curl & jq
command: nix-env -iA nixpkgs.curl nixpkgs.jq
- run:
name: Schedule a Turtle deploy
command: |
echo "We're going to deploy << parameters.platform >> Turtles to << parameters.env >>"
./scripts/deploy.sh "<< parameters.platform >>" "<< parameters.env >>"
jobs:
build:
executor: nix
@@ -169,14 +186,14 @@ jobs:
- run: yarn
- save_yarn_cache
- restore_workingdir_cache:
sdk_version: sdk32
sdk_version: sdk35
platform: ios
- run:
name: Run iOS smoke tests
command: ./scripts/tests/runIOSSmokeTestsCI.sh
- save_workingdir_cache:
workingdir: /Users/distiller/project/workingdir
sdk_version: sdk32
sdk_version: sdk35
platform: ios
android_smoke_tests:
@@ -203,6 +220,34 @@ jobs:
sdk_version: sdk32
platform: android
android_staging_deploy:
executor: nix
steps:
- deploy_turtle:
platform: android
env: staging
android_production_deploy:
executor: nix
steps:
- deploy_turtle:
platform: android
env: production
ios_staging_deploy:
executor: nix
steps:
- deploy_turtle:
platform: ios
env: staging
ios_production_deploy:
executor: nix
steps:
- deploy_turtle:
platform: ios
env: production
workflows:
checks:
jobs:
@@ -212,3 +257,25 @@ workflows:
- unit_tests
- ios_smoke_tests
- android_smoke_tests
deploy:
jobs:
- android_staging_approve_deploy:
type: approval
- android_staging_deploy:
requires:
- android_staging_approve_deploy
- android_production_approve_deploy:
type: approval
- android_production_deploy:
requires:
- android_production_approve_deploy
- ios_staging_approve_deploy:
type: approval
- ios_staging_deploy:
requires:
- ios_staging_approve_deploy
- ios_production_approve_deploy:
type: approval
- ios_production_deploy:
requires:
- ios_production_approve_deploy
+10 -6
View File
@@ -8,16 +8,20 @@ source_local() {
watch_file $file
}
source_up || true
source_local
if [[ "$CI" != "true" && (-z "$GITHUB_TOKEN" || -z "$CIRCLE_API_USER_TOKEN") ]]; then
yellow=`tput setaf 3`
reset=`tput sgr0`
echo "${yellow}please set GITHUB_TOKEN and CIRCLE_API_USER_TOKEN env variables in .envrc.local file if you wish to release turtle-cli"
echo "run 'cp .envrc.local.example .envrc.local' if you don't have one yet and edit the new file${reset}"
fi
export NODE_ENV=development
export EXPO_TURTLE_TOOLS_DIR="$(pwd)/tools"
if [ -z "$EXPO_UNIVERSE_DIR" ]; then
PATH_add $EXPO_TURTLE_TOOLS_DIR/bin
if [ "$CI" = "true" ]; then
PATH_add $EXPO_TURTLE_TOOLS_DIR/ci/bin
fi
PATH_add $EXPO_TURTLE_TOOLS_DIR/bin
if [ "$CI" = "true" ]; then
PATH_add $EXPO_TURTLE_TOOLS_DIR/ci/bin
fi
+2
View File
@@ -0,0 +1,2 @@
export GITHUB_TOKEN=__PUT_YOUR_GITHUB_TOKEN_HERE__ # follow the guide to create one: https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line
export CIRCLE_API_USER_TOKEN=__PUT_YOUR_CIRCLECI_API_TOKEN_HERE__ # create one here: https://circleci.com/account/api
+38
View File
@@ -0,0 +1,38 @@
---
name: "\U0001F41B Bug Report"
about: You want to report a reproducible bug or regression in turtle-cli.
title: ''
labels: 'bug'
assignees: ''
---
<!-- Thanks for helping expo! Before you submit your issue, please make sure you followed our checklist and check the appropriate boxes by putting an x in the [ ]: [x] -->
### New Issue Checklist
- [ ] Updated turtle-cli to the latest version (`yarn global add turtle-cli` or `npm install --global turtle-cli`).
- [ ] I read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
- [ ] I read [docs.expo.io](https://docs.expo.io) (Managed Workflow > Distributing Your App).
- [ ] I searched for [existing GitHub issues](https://github.com/expo/turtle/issues).
- [ ] **I enclosed the complete output when running turtle, including the stack trace and command used.**
### Issue Description
<!-- Please include what's happening, expected behavior, and any relevant code samples -->
##### Command executed
<!-- The command you executed on the command line that resulted in an error -->
##### Complete output when running turtle, including the stack trace and command used
<details>
<pre> [PUT LOGS HERE] </pre>
</details>
### Environment
<!-- Please run `expo diagnostics` and copy the output below. This will help us help you. -->
<details>
<pre> [PUT OUTPUT HERE] </pre>
</details>
+22
View File
@@ -0,0 +1,22 @@
---
name: "\U0001F64B Feature Request"
about: Want us to add something to turtle-cli?
title: ''
labels: 'enhancement'
assignees: ''
---
### Feature Request
#### Motivation Behind Feature
<!-- Why should this feature be implemented? What problem does it solve? -->
#### Feature Description
<!-- Describe your feature request in detail -->
<!-- Please provide any code examples or screenshots of what this feature would look like -->
<!-- Are there any drawbacks? Will this break anything for existing users? -->
#### Alternatives or Workarounds
<!-- Describe alternatives or workarounds you are currently using -->
<!-- Are there ways to do this with existing commands? -->
+21
View File
@@ -0,0 +1,21 @@
---
name: "\U00002753 Questions and discussions"
about: You have a question about turtle-cli or want to discuss some aspects of turtle-cli.
title: ''
labels: 'question'
assignees: ''
---
### Question Checklist
- [ ] I read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
- [ ] I read [docs.expo.io](https://docs.expo.io) (Managed Workflow > Distributing Your App).
- [ ] I searched for [existing GitHub issues](https://github.com/expo/turtle/issues).
### Question Subject
<!-- What command do you have a question about? -->
<!-- Is this a question about documentation? -->
#### Question Description
<!-- Please include expected behavior and any relevant code samples with your question if possible -->
-11
View File
@@ -1,11 +0,0 @@
# Why
Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests.
# How
How did you build this feature or fix this bug and why?
# Test Plan
Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction.
+15
View File
@@ -0,0 +1,15 @@
<!-- Thanks for contributing to _turtle_! Before you submit your pull request, please make sure to check the following boxes by putting an x in the [ ] (don't: [x ], [ x], do: [x]) -->
### Checklist
- [ ] I've read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
- [ ] I've updated the [CHANGELOG](https://github.com/expo/turtle/blob/master/CHANGELOG.md) if necessary.
- [ ] I've ensured the unit and smoke tests are still passing - either by running `yarn test:unit` and `yarn test:smoke:[ios|android]` or by checking the appropriate CircleCI builds' statuses.
- [ ] **I've manually tested whether the changes I made work as expected.**
### Motivation and Context
<!-- Why is this change required? What problem does it solve? -->
<!-- If it fixes an open issue, please link to the issue here. -->
### Description
<!-- Describe your changes in detail -->
<!-- Please describe in detail how you tested your changes. -->
+4 -3
View File
@@ -1,14 +1,15 @@
!/src/node_modules
node_modules
yarn-error.log
google-cloud-credentials.json
/build/
/workingdir/*
/artifacts/*
.history
shell.apk
.secrets*
*.swp
*.swo
.envrc.local
+3
View File
@@ -8,5 +8,8 @@
},
"github": {
"release": true
},
"hooks": {
"after:release": "yarn release:update:turtle-cli-example"
}
}
+1
View File
@@ -6,3 +6,4 @@ SENTRY_DSN=""
ENVIRONMENT="development"
REDIS_URL="redis://localhost:6379/0"
REDIS_CONFIG_URL="redis://localhost:6379/0"
TURTLE_SDK_VERSIONS_SECRET_TOKEN="xeiw7yigha<a_r5aich!oW9Ik2eish8the9Na6Jae-ghoo5ua/t8nu5AeheiTew4"
+369 -6
View File
@@ -1,162 +1,525 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## Unreleased
### Changed
- Replace `/` with `__` in the artifact filename to fix a strange bug with selecting APK file in Android Studio.
- Print currently using Java version if it's not 8.
## [0.13.10] - 2020-03-09
### Added
- Added validation for `--public-url`.
### Changed
- Changed the way of installing NDK - it's installed with `sdkmanager` now.
- Upgraded NDK to 17.2.4988734.
### Fixed
- A bug where the `platform` field in logs wasn't set correctly when using a shortcut command.
- Removed all remaining instances of `UIWebView` in iOS app builds.
## [0.13.9] - 2020-02-13
### Fixed
- Fixed Notifications.getDevicePushTokenAsync() erroring occasionally on iOS SDK 36.
## [0.13.8] - 2020-01-27
### Fixed
- Fixed `react-native-maps` native module not being properly initialized (https://github.com/expo/expo/pull/6844)
- Fixed Android standalone apps crashing on startup (https://github.com/expo/expo/pull/6825)
## [0.13.7] - 2020-01-15
### Added
- Bumped `traveling-fastlane` to 1.11.4 to update CA certs
## [0.13.6] - 2019-12-17
### Fixed
- Fixed issue with missing request handler for assets-library urls.
## [0.13.4] - 2019-12-13
### Added
- Support for building iOS apps with a wildcard provisioning profile.
## [0.13.3] - 2019-12-12
### Fixed
- Removed private API usage from iOS SDK 36 tarball
## [0.13.2] - 2019-12-10
### Fixed
- Fixed Android App Bundle builds
- Fixed issue with Root View Background Color and AppLoading on Android SDK 36 builds
## [0.13.1] - 2019-12-09
### Fixed
- Fixed Android shell app for SDK 36
## [0.13.0] - 2019-12-09
### Added
- Added iOS and Android shell apps for SDK 36
### Changed
- Updated iOS client shell app to support SDK 36
## [0.12.12] - 2019-11-22
### Fixed
- A bug that caused `expo.owner` value not to be used if defined.
## [0.12.11] - 2019-11-20
### Added
- Bumped `traveling-fastlane` to 1.11.0
## [0.12.10] - 2019-11-15
### Added
- Add `shellAppSdkVersion` param to `IOSShellAppBuilder` so entitlement keys get properly added in (https://github.com/expo/turtle/pull/162)
## [0.12.9] - 2019-11-14
### Added
- Support for customizing Facebook SDK behavior at buildtime (autoinitialization, logging app events, logging Advertiser ID) (https://github.com/expo/expo/pull/5924)
## [0.12.8] - 2019-10-29
### Changed
- Updated Android shell app for SDK 35 to fix `Linking.openUrl` not opening app if it's already foregrounded (https://github.com/expo/expo/issues/6058)
- Enforce Java 8 when using turtle-cli.
## [0.12.7] - 2019-10-25
### Changed
- Updated Android shell app for SDK 35 to fix occasional crash in background due to GCM registration service (https://github.com/expo/expo/issues/4207)
## [0.12.5] - 2019-10-18
### Changed
- Updated iOS shell app for SDK 35 to fix crash when calling `WebBrowser.dismissBrowser` on iOS 13 (https://github.com/expo/expo/issues/5742)
## [0.12.4] - 2019-10-11
### Changed
- Updated Android shell app for SDK 35 to fix occasional crash on launch (https://github.com/expo/expo/issues/5917)
## [0.12.3] - 2019-10-09
### Changed
- Updated iOS client shell app for SDK 35 to fix it from crashing on startup due to having an incomplete GoogleService-Info.plist file.
## [0.12.2] - 2019-09-27
### Changed
- Updated Android shell app for SDK 35 to fix crash on Android <=7 due to battery module
## [0.12.1] - 2019-09-20
### Changed
- Updated iOS shell apps for SDK 33 and 34 to fix iOS 13 issues with fishhook, notification tokens, and ShareSheet
- Updated iOS shell app for SDK 35 with a minor fix
## [0.12.0] - 2019-09-19
### Added
- Support for SDK 35 iOS and Android builds.
### Removed
- Support for SDK 27-30 iOS and Android builds.
## [0.11.3] - 2019-09-19
### Changed
- Updated SDK34 Android shell app with `expo-branch` fixes.
## [0.11.2] - 2019-08-21
### Added
- Support for GoogleService-Info.plist (>=34.0.0).
## [0.11.1] - 2019-08-08
### Changed
- Updated iOS client shell app with the latest fixes (up to 2.12.3).
## [0.11.0] - 2019-08-07
### Changed
- Enabled back optional modules support, but only for specific unimodules.
- Updated SDK34 Android shell app with the latest fixes (up to 2.12.2).
- Updated SDK34 iOS shell app with the latest fixes (up to 2.12.3).
## [0.10.0] - 2019-08-01
### Changed
- Fully disabled optional modules on Android for now.
- Updated iOS shell apps for SDK 33 and 34 to fix scoped permissions issue.
- Updated Android shell app for SDK 34 to work after disabling optional modules.
## [0.9.1] - 2019-07-29
### Changed
- `release-it` version to `12.3.4`.
## [0.9.0] - 2019-07-29
### Added
- Android, iOS standalone shell apps and iOS Expo client shell app for SDK34.
- Xcode license check for iOS builds.
### Fixed
- Setting `Constants.nativeAppVersion` for Android standalone builds (actually fixed in [expo/expo-cli#878](https://github.com/expo/expo-cli/pull/878)).
- Passing `expo.android.config` object from `app.json` to the Android builder.
- Fixed crash on launch for iOS standalone apps on iOS 13 (all SDK versions).
- Fixed occasional issue on iOS (SDK 33) where the JS bundle cannot be found ("No cache exists for this resource: shell-app.bundle") and a reload would be required.
## [0.8.11] - 2019-07-16
### Fixed
- Android debug builds.
## [0.8.10] - 2019-07-16
### Fixed
- iOS simulator builds.
## [0.8.9] - 2019-07-15
### Fixed
- User authentication.
## [0.8.8] - 2019-07-11
### Fixed
- LocalAuthentication module on iOS (fixes [expo/expo#663](https://github.com/expo/expo/issues/663)).
## [0.8.7] - 2019-07-05
### Added
- Adhoc Builds: use provisioningProfileId if specified.
- Registering supported SDK versions in Redis.
- Support for 64 bit builds in SDK33.
## [0.8.6] - 2019-06-25
### Added
- Added support for Android build modes: debug or release.
### Fixed
- Upgrading the shell app for a given SDK version when the previous version is already downloaded (bug in `turtle-cli`).
- Updated Android shell app for SDK33 to include `[email protected]` which fixes crashes on Android 9.0 when showing some Lottie animations.
- Schema for `buildModes`.
- Updated @expo/xdl to 55.0.7 (fixed reading from binary plist).
## [0.8.4] - 2019-06-13
### Changed
- Upgraded `sharp` from `0.21.3` to `0.22.1`.
- `gulp-cli` is no longer required to build an app with `turtle-cli`.
## [0.8.3] - 2019-06-13
### Added
- Running Android Turtle process with `supervisor` (pod is restarted if there were 5 failures in the last 10 minutes).
### Changed
- `turtle-cli` is now fetching the app manifest before running the build.
## [0.8.2] - 2019-06-11
### Changed
- Updated Android shell app for SDK33 to remove `expo-face-detector` and `expo-payments-stripe` from standalone builds.
- Updated Android shell app for SDK33 to get rid of `node_modules` for `tools-public`.
- From now on, `turtle-cli` installs dependencies for `tools-public` in shell apps for SDK versions < 33.
### Fixed
- Android builds with turtle-cli by installing all unmodules if `dependencies` is empty.
## [0.8.1] - 2019-06-10
### Changed
- Add expo dependencies when resolving unimodules.
### Fixed
- Support for Android tarballs without `universe-package.json`.
## [0.8.0] - 2019-06-07
### Added
- Turtle CLI logo to the project (created by [@zularizal](https://github.com/zularizal))!
- Shell apps for SDK 33.
- Support for Android App Bundles.
- Support for Android App Bundles (App bundles are built by default, use `-t apk` to build apk).
### Changed
- Updated Android shell app for SDK 32 to fix AppAuth issue (https://github.com/expo/expo/pull/4115) and to fix a newer than expected JSC version.
- Default value for build timeout to 15 minutes.
- Added filtering of logs (strips out download progress) when downloading SDK tools.
- `xdl` -> `@expo/xdl`, updated `@expo/xdl`.
### Fixed
- Generating Android keystore in turtle when one is not passed to turtle-cli (https://github.com/expo/turtle/pull/65).
- Upload logs to s3 if build has been canceled or timed out.
- Unhandled exception on asset download (xdl).
## [0.7.2] - 2019-05-09
### Added
- Support for Android tarballs without `universe-package.json`.
### Changed
- Upgraded `@expo/traveling-fastlane-darwin` to 1.9.4 (fixes issues with generating provisioning profiles for ad-hoc builds).
### Removed
- Support for `CLIENT_LOGGER_LEVEL` env variable.
## [0.7.1] - 2019-05-06
### Fixed
- Resolving `fastlane` version when `LC_ALL` is not set.
## [0.7.0] - 2019-05-06
### Added
- Support for custom Android builds.
### Changed
- Refactored logger.
### Fixed
- `platform` log field wrongly set to `ios` for Android builds (when using `turtle-cli`).
- Brought back `jobID` and `experienceName` fields to Android logs.
## [0.6.1] - 2019-04-23
### Added
- Checking fastlane version before running build (turtle-cli).
### Changed
- Updated iOS shell app for SDK 32 to fix AppAuth issue.
- Babel replaced by ttypescript.
- Updated xdl to 53.5.3 and @expo/spawn-async to 1.4.2, so that error stack traces should be more informative now.
### Fixed
- Brought back `jobID` and `experienceName` fields to GCloud logs.
### Removed
- `buidAndroidTarballLocally.sh` script (it has been moved to expo repository - [expo/expo#4022](https://github.com/expo/expo/pull/4022)).
## [0.6.0] - 2019-04-09
### Changed
- Removed Branch module from Android shell apps for all SDK versions.
## [0.5.15] - 2019-04-03
### Added
- Turtle smoke tests are now being executed on CircleCI from the context of this repository.
### Changed
- Updated iOS shell app for SDK 32 (fixes [this loading issue for slow connections](https://github.com/expo/expo/issues/3574)).
- Minor infra changes (doesn't affect users).
- Error logs format - error objects are now passed in an object being passed as the first argument to logger function.
### Removed
- Sending logs to loggly.
## [0.5.14] - 2019-03-22
### Added
- `--config` parameter for turtle-cli commands, which allows to specify a custom path to app.json file
### Changed
- Updated iOS shell app for SDK 32 (fixes [this notifications issue](https://github.com/expo/expo/issues/3663)).
## [0.5.13] - 2019-03-12
### Added
- Android SDK version support validation.
### Changed
- iOS Enterprise builds don't compile bitcode now.
## [0.5.12] - 2019-02-26
### Added
- Google Cloud logger (as a bunyan stream).
### Changed
- Android builder passes the manifest from a build job message if it's available.
## [0.5.11] - 2019-02-22
### Added
- Builder for iOS client apps.
## [0.5.10] - 2019-02-19
### Added
- Register Turtle version in Redis.
- Registering Turtle version in Redis.
### Changed
- Update Android shell app for SDK 32 to fix [update](https://github.com/expo/expo/issues/3504) and [back button](https://github.com/expo/expo/issues/1786) issues.
## [0.5.9] - 2019-02-06
- Update iOS shell app for SDK 32 (fixes bare notifications [issue](https://github.com/expo/expo/issues/3223)).
## [0.5.7] - 2019-01-31
- Update Android shell app for SDK 32 to fix bundled assets issue.
## [0.5.6] - 2019-01-25
- Update iOS shell app for SDK 30, 31 and 32 (built with xcode 10.1).
## [0.5.5] - 2019-01-24
### Added
- Sending build duration in AWS SQS messages (of `FINISHED` and `ERRORED` types).
## [0.5.4] - 2019-01-22
### Changed
- Update iOS shell app for SDK32 to [`expo/expo#0847c10`](https://github.com/expo/expo/commit/0847c1073d38c366866f3d9279ddd662da47dc9b), i.e. v2.10.3 with fixed WebView navigation scheme and upgraded Facebook SDK.
## [0.5.3] - 2019-01-21
### Fixed
- Building Android standalone apps ([not accepted license issue](https://github.com/expo/expo/issues/3266)) - updated Android build tools (`build-tools;28.0.3`, `platforms;android-28`).
## [0.5.2] - 2019-01-18
### Added
- The link (in README) to the repository containing `turtle-cli` usage example.
- [Contributing guide](CONTRIBUTING.md).
- [Code of Conduct](CODE_OF_CONDUCT.md).
### Removed
- `eslint`
### Changed
- Fix all `tslint` errors.
## [0.5.1] - 2019-01-16
### Changed
- Update Android shell app for SDK32 that includes `[email protected]`.
## [0.5.0] - 2019-01-16
### Added
- Turtle version is added to the `onFinish` and `onError` build messages.
### Changed
- A version property value being sent to the queue. It's now the version number
from `package.json` instead of `new`/`old` indicator.
from `package.json` instead of `new`/`old` indicator.
### Removed
- `--push-p12-path` parameter for `turtle build:ios` command,
a Push Notifications Certificate is no longer required to perform a successful
iOS standalone app build.
a Push Notifications Certificate is no longer required to perform a successful
iOS standalone app build.
## [0.4.3] - 2019-01-09
### Changed
- Update iOS shell app for SDK32.
- Update Android shell app for SDK32.
+2 -5
View File
@@ -16,9 +16,6 @@ This repository contains the codebase for the `turtle-cli` NPM package. The same
### Branches
The `master` branch of the repository should be kept releasable at any time. This way we can continuously release fixes and improvements without costly managing of different branches and issues will be noticed and fixed quickly. This also ensures other contributors can check out the latest version from GitHub and work on it with minimal disruption from other features in progress.
## Setting up the repository for development
*TODO*
## Submitting a pull request
To submit a pull request:
1. Fork the [repository](https://github.com/expo/turtle) and create a feature branch. (Existing contributors can create feature branches without forking. Prefix the branch name with `@your-github-username/`.)
@@ -27,7 +24,7 @@ To submit a pull request:
4. Wait for a review and adjust the code if necessary.
## Publishing a release
- Make sure you have set `GITHUB_TOKEN` and `CIRCLE_API_USER_TOKEN` environment variables in `.envrc.local` file. If you don't have the file, run `cp .envrc.local.example .envrc.local` and edit the file.
- To release a new version of `turtle-cli`, run `yarn release` command.
- If you wish to release a new *beta* version of `turtle-cli`, run `yarn release:beta` instead.
- Update [Changelog](CHANGELOG.md).
- In a terminal, `cd` into [expo/turtle-cli-example](https://github.com/expo/turtle-cli-example) repository, run `yarn update-turtle-cli-version` (this script updates `turtle-cli` version number in CI configuration files and commits the changes) and then run `git push`. Thanks!
- Update the [changelog](CHANGELOG.md).
+35
View File
@@ -0,0 +1,35 @@
# Turtle Development
## Prerequisites
- Working `www` service, see [this README](https://github.com/expo/universe/tree/master/server/www/README.md) for more details.
- Own AWS SQS queues. See [this README](https://github.com/expo/universe/tree/master/terraform/turtle-queues/README.md) to learn more.
## Setup
- Run `update-local-secrets` to populate the `.secrets*` files. You'll need to run this any time any secret changes (it shouldn't be very often).
- Run `EXPO_UNIVERSE_DIR=/path/to/universe/dir yarn secrets:init-private YOUR_SQS_NICKNAME`. Alternatively, you can create `.secrets.local-queue` file with the SQS queues' urls yourself (`AWS_SQS_OUT_QUEUE_URL`, `AWS_SQS_ANDROID_QUEUE_URL`, `AWS_SQS_ANDROID_PRIORITY_QUEUE_URL`, `AWS_SQS_IOS_QUEUE_URL`, `AWS_SQS_IOS_PRIORITY_QUEUE_URL`)
- Run `yarn set-workingdir:local` or `yarn set-workingdir:remote`:
- `:local` creates symlinks to the shell apps in `expo` repository (_unfortunately this is currently broken_)
- `:remote` downloads precompiled shell apps
- Run `yarn` to install node modules.
- Run `yarn start:ios` or `yarn start:android` to run Turtle.
## Updating shell apps
_TODO_
## Generating recording files for smoke tests
Smoke tests are powered by [Nock](https://www.npmjs.com/package/nock) which uses JSON files containing responses to the HTTP requests fired by the build process.
To record new responses remove old `recording.json` and run tests and then manually schedule a build with `expo-cli` tool.
As a precaution, the file with HTTP requests/responses contains, among other things, iOS certificates used for the test build, is
encrypted with `git-crypt`. Remember not to revoke them, because then the tests will fail.
## Other notes
Turtle uses Redis to get notifications (from www) about builds cancellations. To make this feature working, you have to use the same Redis instance as www. Therefore, you need to remember about starting www before starting Turtle. If you forget about it, don't worry, Turtle will remind you to run `yarn start-docker` in `server/www` directory.
Turtle uploads build artifacts to S3. This could take some time if you have a poor internet connection. To facilitate local development, there is a feature which allows Turtle to fake artifacts upload. `secrets:init-private` script, which you should have run while setting up Turtle, sets fake upload directory to your user's default `Downloads` directory (we're assuming you're using Mac). If you need to test uploading artifacts to S3, you have to edit `.secrets.local` file and comment or remove `TURTLE_FAKE_UPLOAD` and `TURTLE_FAKE_UPLOAD_DIR` environment variables.
+5 -102
View File
@@ -1,104 +1,5 @@
FROM openjdk:8u141
ENV DEBIAN_FRONTEND noninteractive
# https://github.com/yarnpkg/yarn/issues/2821
RUN apt-get update && apt-get install apt-transport-https
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
# Install dependencies
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -yq \
ant\
build-essential\
bzip2:i386\
file\
lib32ncurses5\
lib32z1\
libc6:i386\
libncurses5:i386\
libstdc++6:i386\
rsync\
unzip\
yarn\
zlib1g:i386\
--no-install-recommends && \
apt-get clean
ENV NPM_CONFIG_LOGLEVEL warn
ENV NODE_VERSION 8.12.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
# Download and untar SDK
ENV ANDROID_HOME /usr/local/android-sdk-linux
ENV ANDROID_SDK /usr/local/android-sdk-linux
ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
RUN mkdir -p ${ANDROID_HOME} && \
curl -L "${ANDROID_SDK_URL}" > ${ANDROID_HOME}/sdk.zip && \
cd ${ANDROID_HOME} && \
unzip -qq sdk.zip && \
rm sdk.zip && \
mkdir -p ${HOME}/.android && \
touch ${HOME}/.android/repositories.cfg
ENV PATH ${ANDROID_HOME}/platform-tools:${PATH}
ENV PATH ${ANDROID_HOME}/tools:${PATH}
ENV PATH ${ANDROID_HOME}/tools/bin:${PATH}
ENV PATH ${ANDROID_HOME}/build-tools/28.0.3/:${PATH}
RUN yes | sdkmanager --licenses > /dev/null
RUN yes | sdkmanager \
"platforms;android-23" \
"platforms;android-24" \
"platforms;android-25" \
"platforms;android-26" \
"platforms;android-27" \
"platforms;android-28" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager "platform-tools" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager "build-tools;28.0.3" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager \
"extras;android;m2repository" \
"extras;google;m2repository" \
"extras;google;google_play_services" | grep -v '=' || echo 'no output'
# Install Android NDK
ENV ANDROID_NDK_VERSION android-ndk-r10e
ENV ANDROID_NDK_FILE ${ANDROID_NDK_VERSION}-linux-x86_64.bin
ENV ANDROID_NDK_URL https://dl.google.com/android/ndk/${ANDROID_NDK_FILE}
ENV ANDROID_NDK /opt/${ANDROID_NDK_VERSION}
ENV PATH $ANDROID_NDK:$PATH
# i have no clue why some of this is here, but it's working elsewhere
# it appears to install the NDK version expo needs, so that's cool
RUN mkdir /ndk_setup && cd /ndk_setup && \
curl -L ${ANDROID_NDK_URL} > ${ANDROID_NDK_FILE} && \
chmod +x ${ANDROID_NDK_FILE} && \
sync && \
./${ANDROID_NDK_FILE} && \
mv ./${ANDROID_NDK_VERSION} ${ANDROID_NDK} && \
cp -R \
${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64 \
${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86 && \
cp -R \
${ANDROID_NDK}/toolchains/x86-4.8/prebuilt/linux-x86_64 \
${ANDROID_NDK}/toolchains/x86-4.8/prebuilt/linux-x86 && \
cd && rm -rf /ndk_setup
# Support Gradle
ENV TERM dumb
# Install gradle
RUN wget https://services.gradle.org/distributions/gradle-4.4-all.zip
RUN unzip -qq gradle-4.4-all.zip
RUN mv gradle-4.4 /usr/local
RUN rm gradle-4.4-all.zip
ENV GRADLE_HOME /usr/local/gradle-4.4
ENV PATH ${GRADLE_HOME}/bin:$PATH
# see docker-base/Dockerfile to learn what's installed in the turtle-android-base image
FROM gcr.io/exponentjs/turtle-android-base:0.1.3
ADD . /app/turtle
@@ -123,4 +24,6 @@ ENV TURTLE_WORKING_DIR_PATH /app/turtle/workingdir/
WORKDIR /app/turtle
CMD ["node", "./build/server.js"]
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]
+6 -6
View File
@@ -15,21 +15,20 @@ Turtle CLI is a command line interface for building Expo standalone apps.
You can use it both on your CI and your private computer.
- [Changelog](CHANGELOG.md)
- [Contributing to Turtle CLI](CONTRIBUTING.md)
- [Contributing](CONTRIBUTING.md)
- [Development](DEVELOPMENT.md)
- [Code of Conduct](CODE_OF_CONDUCT.md)
## Glossary
- **Turtle** - script which takes a shell app, fills it with user's code and produces a standalone app
- **Shell app** — precompiled (in case of iOS builds) Expo app which doesn't have user's code
- **Standalone app** - .ipa/.apk file, a user uploads standalone apps to the Google Play Store/Apple App Store
## Installation
[Installation instructions and documentation here.](https://docs.expo.io/versions/latest/distribution/turtle-cli)
## Usage example
See the [expo/turtle-cli-example](https://github.com/expo/turtle-cli-example) repository to learn how to use Turtle CLI in order to build Expo standalone apps on your CI.
## Do you need help?
- Make sure you've read [the Expo Docs](https://docs.expo.io/), especially [Building Standalone Apps on Your CI
](https://docs.expo.io/versions/latest/distribution/turtle-cli) and [Building Standalone Apps](https://docs.expo.io/versions/latest/distribution/building-standalone-apps) guides.
- Search for existing GitHub issues [in this repository](https://github.com/expo/turtle/issues) and in [expo/expo](https://github.com/expo/expo/issues) repository.
@@ -39,5 +38,6 @@ See the [expo/turtle-cli-example](https://github.com/expo/turtle-cli-example) re
* ask a question on [Expo Developers Slack](http://slack.expo.io).
## License
The Turtle CLI source code is made available under the [MIT license](LICENSE).
Some of the dependencies are licensed differently, with the BSD license, for example.
+12 -1
View File
@@ -3,7 +3,18 @@
const subcommand = process.argv[2];
if (subcommand) {
const [, platform] = subcommand.split(':');
let platform;
if (subcommand.length === 2) {
const letter = subcommand[1];
if (letter === 'a') {
platform = 'android';
} else if (letter === 'i') {
platform = 'ios';
}
} else {
const [, maybePlatform] = subcommand.split(':');
platform = maybePlatform;
}
if (platform === 'ios' || platform === 'android') {
// so that logs have correct platform set
process.env.PLATFORM = platform;
+104
View File
@@ -0,0 +1,104 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const nock_1 = __importDefault(require("nock"));
const config_1 = __importDefault(require("../config"));
const constants_1 = require("../constants");
const jobManager = __importStar(require("../jobManager"));
const logger_1 = __importDefault(require("../logger"));
jest.mock('../builders/utils/uploader.ts', () => ({
uploadBuildToS3: jest.fn(() => {
logger_1.default.debug('Faking uploading build');
return 'legit_path';
}),
}));
async function performSmokeTest(recording) {
jest.setTimeout(60 * 60 * 1000);
// @ts-ignore
const fixtureExists = await fs_extra_1.default.exists(recording);
if (fixtureExists) {
logger_1.default.info('Fixture exists, test will use existing one.');
nock_1.default.load(recording);
mockLogs();
mockSQS();
logger_1.default.info('Loading fixture');
}
else {
nock_1.default.recorder.rec({
dont_print: true,
output_objects: true,
enable_reqheaders_recording: false,
});
}
await jobManager.doJob();
if (!fixtureExists) {
await fs_extra_1.default.writeFile(recording, JSON.stringify(nock_1.default.recorder.play()));
}
}
function mockLogs() {
/*
Match log push messages. Seperate matcher, because it needs `persist` option
due to fact that it's being called variable amount times.
*/
return nock_1.default('https://exp-shell-app-assets.s3.us-west-1.amazonaws.com')
.persist()
.put((uri) => {
return uri.indexOf('/logs') >= 0;
})
.reply(200);
}
function mockSQS() {
return nock_1.default('https://sqs.us-west-2.amazonaws.com')
.persist()
.post(() => true)
.reply(200);
}
function mockFinish() {
// A separate matcher for the final request to ensure build was completed successfully
return nock_1.default('https://sqs.us-west-2.amazonaws.com:443')
.post('/', (body) => {
const keys = Object.keys(body);
if (keys.includes('MessageBody')) {
const mb = JSON.parse(body.MessageBody);
if (mb.status === 'finished') {
return true;
}
else if (mb.status === 'errored') {
fail('Build ended with error');
}
}
return false;
})
.reply(200);
}
async function testPlatform(platform) {
process.env.PLATFORM = platform;
const utils = require('turtle/aws/utils');
utils.QUEUE_URL = jest.fn((priority) => {
return config_1.default.sqs.queues[priority][platform];
});
nock_1.default.cleanAll();
nock_1.default.enableNetConnect();
const finishMock = mockFinish();
const fixtureLocation = `src/__smoke__/fixtures/${platform}/recording.json`;
await performSmokeTest(fixtureLocation);
expect(finishMock.isDone());
nock_1.default.disableNetConnect();
}
test('Android builds', async () => {
await testPlatform(constants_1.PLATFORMS.ANDROID);
});
test('iOS builds', async () => {
await testPlatform(constants_1.PLATFORMS.IOS);
});
//# sourceMappingURL=smoke.test.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"smoke.test.js","sourceRoot":"","sources":["../../src/__smoke__/smoke.test.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\n\nimport nock from 'nock';\n\nimport config from 'turtle/config';\nimport { PLATFORMS } from 'turtle/constants';\nimport * as jobManager from 'turtle/jobManager';\nimport logger from 'turtle/logger';\n\njest.mock('../builders/utils/uploader.ts', () => ({\n uploadBuildToS3: jest.fn(() => {\n logger.debug('Faking uploading build');\n return 'legit_path';\n }),\n}));\n\nasync function performSmokeTest(recording: string) {\n jest.setTimeout(60 * 60 * 1000);\n\n // @ts-ignore\n const fixtureExists = await fs.exists(recording);\n if (fixtureExists) {\n logger.info('Fixture exists, test will use existing one.');\n\n nock.load(recording);\n mockLogs();\n mockSQS();\n logger.info('Loading fixture');\n } else {\n nock.recorder.rec({\n dont_print: true,\n output_objects: true,\n enable_reqheaders_recording: false,\n });\n }\n\n await jobManager.doJob();\n if (!fixtureExists) {\n await fs.writeFile(recording, JSON.stringify(nock.recorder.play()));\n }\n}\n\nfunction mockLogs() {\n /*\n Match log push messages. Seperate matcher, because it needs `persist` option\n due to fact that it's being called variable amount times.\n */\n return nock('https://exp-shell-app-assets.s3.us-west-1.amazonaws.com')\n .persist()\n .put((uri: string) => {\n return uri.indexOf('/logs') >= 0;\n })\n .reply(200);\n}\n\nfunction mockSQS() {\n return nock('https://sqs.us-west-2.amazonaws.com')\n .persist()\n .post(() => true)\n .reply(200);\n}\n\nfunction mockFinish() {\n // A separate matcher for the final request to ensure build was completed successfully\n\n return nock('https://sqs.us-west-2.amazonaws.com:443')\n .post('/', (body: any) => {\n const keys = Object.keys(body);\n if (keys.includes('MessageBody')) {\n const mb = JSON.parse(body.MessageBody);\n if (mb.status === 'finished') {\n return true;\n } else if (mb.status === 'errored') {\n fail('Build ended with error');\n }\n }\n return false;\n })\n .reply(200);\n}\n\nasync function testPlatform(platform: string) {\n process.env.PLATFORM = platform;\n\n const utils = require('turtle/aws/Line truncated
+14
View File
@@ -0,0 +1,14 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const context = __importStar(require("../turtleContext"));
test('Initially should not exit', () => {
expect(context.checkShouldExit()).toBe(false);
});
//# sourceMappingURL=turtleContext.test.js.map
@@ -0,0 +1 @@
{"version":3,"file":"turtleContext.test.js","sourceRoot":"","sources":["../../src/__tests__/turtleContext.test.ts"],"names":[],"mappings":";;;;;;;;;AAAA,0DAAgD;AAEhD,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACrC,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC","sourcesContent":["import * as context from 'turtle/turtleContext';\n\ntest('Initially should not exit', () => {\n expect(context.checkShouldExit()).toBe(false);\n});\n"]}
+21
View File
@@ -0,0 +1,21 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const validator = __importStar(require("../validator"));
const testValidator = (fixturePath) => {
const data = require(fixturePath);
expect(() => validator.sanitizeJob(data)).not.toThrow();
};
test('Passes valid manifest for Android', () => {
testValidator('turtle/__tests__/fixtures/androidJob.json');
});
test('Passes valid manifest for ios', () => {
testValidator('turtle/__tests__/fixtures/iosJob.json');
});
//# sourceMappingURL=validator.test.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../src/__tests__/validator.test.ts"],"names":[],"mappings":";;;;;;;;;AAAA,wDAA8C;AAE9C,MAAM,aAAa,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;AAC1D,CAAC,CAAC;AAEF,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC7C,aAAa,CAAC,2CAA2C,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE;IACzC,aAAa,CAAC,uCAAuC,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC","sourcesContent":["import * as validator from 'turtle/validator';\n\nconst testValidator = (fixturePath: string) => {\n const data = require(fixturePath);\n expect(() => validator.sanitizeJob(data)).not.toThrow();\n};\n\ntest('Passes valid manifest for Android', () => {\n testValidator('turtle/__tests__/fixtures/androidJob.json');\n});\n\ntest('Passes valid manifest for ios', () => {\n testValidator('turtle/__tests__/fixtures/iosJob.json');\n});\n"]}
+5
View File
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXTRA_DIMENSIONS = Symbol('Extra Dimensions');
exports.GROUP_HASH = Symbol('Group Hash');
//# sourceMappingURL=constants.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/constants.ts"],"names":[],"mappings":";;AAAa,QAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC9C,QAAA,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC","sourcesContent":["export const EXTRA_DIMENSIONS = Symbol('Extra Dimensions');\nexport const GROUP_HASH = Symbol('Group Hash');\n"]}
+44
View File
@@ -0,0 +1,44 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = __importDefault(require("../../config"));
exports.TYPE_DIMENSIONS = (type) => [
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'type', Value: type },
],
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'type', Value: type },
{ Name: 'host', Value: config_1.default.hostname },
],
];
exports.PRIORITY_DIMENSIONS = (type, priority) => [
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'priority', Value: priority },
],
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'type', Value: type },
],
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'type', Value: type },
{ Name: 'priority', Value: priority },
],
[
{ Name: 'env', Value: config_1.default.deploymentEnv },
{ Name: 'platform', Value: config_1.default.platform },
{ Name: 'type', Value: type },
{ Name: 'host', Value: config_1.default.hostname },
],
];
//# sourceMappingURL=dimensions.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"dimensions.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/dimensions.ts"],"names":[],"mappings":";;;;;AAAA,0DAAmC;AAEtB,QAAA,eAAe,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;IAC/C;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;KAC9B;IACD;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;QAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;KACzC;CACF,CAAC;AAEW,QAAA,mBAAmB,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE,CAAC;IACrE;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE;KACtC;IACD;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;KAC9B;IACD;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;QAC7B,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE;KACtC;IACD;QACE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAM,CAAC,aAAa,EAAE;QAC5C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;QAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAM,CAAC,QAAQ,EAAE;KACzC;CACF,CAAC","sourcesContent":["import config from 'turtle/config';\n\nexport const TYPE_DIMENSIONS = (type: string) => [\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'type', Value: type },\n ],\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'type', Value: type },\n { Name: 'host', Value: config.hostname },\n ],\n];\n\nexport const PRIORITY_DIMENSIONS = (type: string, priority: string) => [\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'priority', Value: priority },\n ],\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'type', Value: type },\n ],\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'type', Value: type },\n { Name: 'priority', Value: priority },\n ],\n [\n { Name: 'env', Value: config.deploymentEnv },\n { Name: 'platform', Value: config.platform },\n { Name: 'type', Value: type },\n { Name: 'host', Value: config.hostname },\n ],\n];\n"]}
+138
View File
@@ -0,0 +1,138 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const aws_sdk_1 = __importDefault(require("aws-sdk"));
const lodash_1 = __importDefault(require("lodash"));
const constants_1 = require("./constants");
const statistics_1 = __importDefault(require("./statistics"));
const config_1 = __importDefault(require("../../config"));
const logger_1 = __importDefault(require("../../logger"));
const SUCCESS_SUFFIX = '.success';
const FAIL_SUFFIX = '.fail';
const CHUNK_SIZE = 20;
const state = {
metrics: [],
registeredMetrics: {},
intervalId: null,
};
const cloudWatch = new aws_sdk_1.default.CloudWatch({
apiVersion: '2010-08-01',
region: config_1.default.cloudwatch.region,
accessKeyId: config_1.default.aws.accessKeyId,
secretAccessKey: config_1.default.aws.secretAccessKey,
});
function init() {
if (config_1.default.cloudwatch.disabled) {
return;
}
state.intervalId = setInterval(_dumpMetrics, config_1.default.cloudwatch.intervalMs);
}
exports.init = init;
function addMetricData({ name, value, success = true, explicitName = false, extraDimensions = [], }) {
if (config_1.default.cloudwatch.disabled) {
return;
}
const metricName = explicitName ? name : _createMetricName(name, success);
const registeredMetric = state.registeredMetrics[metricName];
if (!registeredMetric) {
return;
}
const { unit } = registeredMetric;
const metric = {
MetricName: metricName,
Unit: unit,
Value: value,
Timestamp: new Date(),
[constants_1.EXTRA_DIMENSIONS]: extraDimensions,
[constants_1.GROUP_HASH]: _calculateGroupHash(metricName, extraDimensions),
};
state.metrics.push(metric);
}
exports.addMetricData = addMetricData;
function registerMetric({ metricName, unit, reducer, dimensions = [], statistics = false, addEmpty = true, explicitName = false, }) {
if (config_1.default.cloudwatch.disabled) {
return;
}
const successMetricName = _createMetricName(metricName, true, explicitName);
state.registeredMetrics[successMetricName] = { unit, statistics, reducer, addEmpty, dimensions };
if (!explicitName) {
const failMetricName = _createMetricName(metricName, false);
state.registeredMetrics[failMetricName] = { unit, statistics, reducer, addEmpty, dimensions };
}
}
exports.registerMetric = registerMetric;
function _createMetricName(name, success, explicitName) {
if (explicitName) {
return name;
}
else {
const suffix = success ? SUCCESS_SUFFIX : FAIL_SUFFIX;
return `${name}${suffix}`;
}
}
function _calculateGroupHash(metricName, extraDimensions) {
const dimString = lodash_1.default.flatten(extraDimensions)
.map(({ Name, Value }) => `,${Name}:${Value}`)
.join('');
return `${metricName}${dimString}`;
}
function _dumpMetrics() {
if (!state.metrics.length && Object.keys(state.registeredMetrics).length < 0) {
// empty metrics list, skipping
return;
}
logger_1.default.trace('[cloudwatch] lenghts for state.metrics=%d, state.registeredMetrics=%d', state.metrics.length, Object.keys(state.registeredMetrics).length);
_addEmptyMetrics(state.metrics);
const formattedMetrics = _formatMetrics(state.metrics);
_pushMetrics(formattedMetrics);
state.metrics = [];
}
function _addEmptyMetrics(metrics) {
const seenMetrics = metrics.reduce((acc, i) => {
if (!acc.has(i.MetricName)) {
acc.add(i.MetricName);
}
return acc;
}, new Set());
const nonEmptyMetrics = lodash_1.default.omitBy(state.registeredMetrics, ({ addEmpty }) => !addEmpty);
const toAdd = lodash_1.default.difference(Object.keys(nonEmptyMetrics), Array.from(seenMetrics));
toAdd.forEach((name) => addMetricData({ name, value: 0, explicitName: true }));
}
function _formatMetrics(metrics) {
const reducedMetrics = _reduceMetrics(metrics);
const metricsWithDimensions = reducedMetrics.map((metric) => {
const { dimensions } = state.registeredMetrics[metric.MetricName];
const joinedDimensions = [...dimensions, ...metric[constants_1.EXTRA_DIMENSIONS]];
return joinedDimensions.map((i) => Object.assign({}, metric, { Dimensions: i }));
});
const metricData = lodash_1.default.flatten(metricsWithDimensions);
const chunks = lodash_1.default.chunk(metricData, CHUNK_SIZE);
return chunks.map((chunk) => ({
Namespace: config_1.default.cloudwatch.namespace,
MetricData: chunk,
}));
}
function _reduceMetrics(metrics) {
const grouped = lodash_1.default.groupBy(metrics, constants_1.GROUP_HASH);
return lodash_1.default.reduce(grouped, (acc, val) => {
const { MetricName: key } = val[0];
const { reducer, statistics } = state.registeredMetrics[key];
const reduced = reducer ? reducer(val) : val;
const withStats = statistics ? statistics_1.default(reduced) : reduced;
acc.push(...withStats);
return acc;
}, []);
}
function _pushMetrics(metrics) {
logger_1.default.trace('[cloudwatch] pushing metrics', JSON.stringify(metrics, null, '\t'));
metrics.forEach((metricsChunk) => {
cloudWatch.putMetricData(metricsChunk, (err) => {
if (err) {
logger_1.default.warn({ err }, '[cloudwatch]');
}
});
});
}
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/index.ts"],"names":[],"mappings":"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 truncated
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function sum(metrics) {
if (metrics.length === 0) {
return [];
}
const reduced = metrics.reduce((acc, i) => {
let result = acc;
if (!result) {
result = { ...i };
}
else {
result.Value += i.Value;
}
return result;
}, null);
return [reduced];
}
exports.sum = sum;
function avg(metrics) {
if (!metrics.length) {
return [];
}
const metric = sum(metrics)[0];
metric.Value = metric.Value / metrics.length;
return [metric];
}
exports.avg = avg;
//# sourceMappingURL=reducers.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"reducers.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/reducers.ts"],"names":[],"mappings":";;AAEA,SAAgB,GAAG,CAAC,OAAkB;IACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QACxB,OAAO,EAAE,CAAC;KACX;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAmB,EAAE,CAAU,EAAE,EAAE;QACjE,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;SACnB;aAAM;YACL,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;SACzB;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,OAAO,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAdD,kBAcC;AAED,SAAgB,GAAG,CAAC,OAAkB;IACpC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO,EAAE,CAAC;KACX;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAY,CAAC;IAC1C,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAC7C,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AARD,kBAQC","sourcesContent":["import { IMetric } from 'turtle/aws/cloudwatch/types';\n\nexport function sum(metrics: IMetric[]) {\n if (metrics.length === 0) {\n return [];\n }\n const reduced = metrics.reduce((acc: IMetric | null, i: IMetric) => {\n let result = acc;\n if (!result) {\n result = { ...i };\n } else {\n result.Value += i.Value;\n }\n return result;\n }, null);\n return [reduced];\n}\n\nexport function avg(metrics: IMetric[]) {\n if (!metrics.length) {\n return [];\n }\n\n const metric = sum(metrics)[0] as IMetric;\n metric.Value = metric.Value / metrics.length;\n return [metric];\n}\n"]}
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function calculateStatistics(metrics) {
if (!metrics.length) {
return [];
}
const reduced = metrics.reduce((acc, i) => {
let result = acc;
if (!result) {
result = Object.assign({}, i, {
StatisticValues: {
Maximum: -Infinity,
Minimum: Infinity,
SampleCount: 0,
Sum: 0.0,
},
Value: undefined,
});
}
result.StatisticValues.Maximum = Math.max(result.StatisticValues.Maximum, i.Value);
result.StatisticValues.Minimum = Math.min(result.StatisticValues.Minimum, i.Value);
result.StatisticValues.SampleCount += 1;
result.StatisticValues.Sum += i.Value;
return result;
}, null);
return [reduced];
}
exports.default = calculateStatistics;
//# sourceMappingURL=statistics.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/statistics.ts"],"names":[],"mappings":";;AAEA,SAAwB,mBAAmB,CAAC,OAAkB;IAC5D,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO,EAAE,CAAC;KACX;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAA2B,EAAE,CAAU,EAAE,EAAE;QACzE,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE;gBAC5B,eAAe,EAAE;oBACf,OAAO,EAAE,CAAC,QAAQ;oBAClB,OAAO,EAAE,QAAQ;oBACjB,WAAW,EAAE,CAAC;oBACd,GAAG,EAAE,GAAG;iBACT;gBACD,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;SACJ;QAED,MAAM,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACnF,MAAM,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACnF,MAAM,CAAC,eAAe,CAAC,WAAW,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,OAAO,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AA1BD,sCA0BC","sourcesContent":["import { IMetric, MetricWithStats } from 'turtle/aws/cloudwatch/types';\n\nexport default function calculateStatistics(metrics: IMetric[]) {\n if (!metrics.length) {\n return [];\n }\n\n const reduced = metrics.reduce((acc: MetricWithStats | null, i: IMetric) => {\n let result = acc;\n if (!result) {\n result = Object.assign({}, i, {\n StatisticValues: {\n Maximum: -Infinity,\n Minimum: Infinity,\n SampleCount: 0,\n Sum: 0.0,\n },\n Value: undefined,\n });\n }\n\n result.StatisticValues.Maximum = Math.max(result.StatisticValues.Maximum, i.Value);\n result.StatisticValues.Minimum = Math.min(result.StatisticValues.Minimum, i.Value);\n result.StatisticValues.SampleCount += 1;\n result.StatisticValues.Sum += i.Value;\n return result;\n }, null);\n return [reduced];\n}\n"]}
+4
View File
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("./constants");
//# sourceMappingURL=types.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/aws/cloudwatch/types.ts"],"names":[],"mappings":";;AAAA,2CAA+E","sourcesContent":["import { EXTRA_DIMENSIONS, GROUP_HASH } from 'turtle/aws/cloudwatch/constants';\n\nexport interface IMetric {\n MetricName: string;\n Unit: string;\n Value: number;\n Timestamp: Date;\n StatisticValues?: {\n Maximum: number;\n Minimum: number;\n SampleCount: number;\n Sum: number;\n };\n [EXTRA_DIMENSIONS]: any;\n [GROUP_HASH]: string;\n}\n\nexport type MetricWithStats = {\n StatisticValues: {\n Maximum: number;\n Minimum: number;\n SampleCount: number;\n Sum: number;\n },\n} & IMetric;\n\nexport interface IMetricData {\n name: string;\n value: number;\n success?: boolean;\n explicitName?: boolean;\n extraDimensions?: any;\n}\n\nexport interface IMetricConfiguration {\n unit: string;\n statistics?: boolean;\n reducer?: any;\n addEmpty?: boolean;\n dimensions?: any;\n}\n\nexport type MetricRegistrationObject = { metricName: string, explicitName?: boolean } & IMetricConfiguration;\n\nexport interface IMetricsChunk {\n Namespace: string;\n MetricData: IMetric[];\n}\n"]}
+25
View File
@@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const aws_sdk_1 = __importDefault(require("aws-sdk"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const lodash_1 = __importDefault(require("lodash"));
const config_1 = __importDefault(require("../config"));
const s3 = new aws_sdk_1.default.S3({
...lodash_1.default.pick(config_1.default.aws, ['accessKeyId', 'secretAccessKey']),
...lodash_1.default.pick(config_1.default.s3, ['region']),
});
exports.default = s3;
async function uploadFile({ bucketName = config_1.default.s3.bucket, key, srcPath }) {
return await s3
.upload({
Bucket: bucketName,
Key: key,
Body: fs_extra_1.default.createReadStream(srcPath),
})
.promise();
}
exports.uploadFile = uploadFile;
//# sourceMappingURL=s3.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/aws/s3.ts"],"names":[],"mappings":";;;;;AAAA,sDAA0B;AAC1B,wDAA0B;AAC1B,oDAAuB;AAEvB,uDAAmC;AAQnC,MAAM,EAAE,GAAG,IAAI,iBAAG,CAAC,EAAE,CAAC;IACpB,GAAG,gBAAC,CAAC,IAAI,CAAC,gBAAM,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzD,GAAG,gBAAC,CAAC,IAAI,CAAC,gBAAM,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,kBAAe,EAAE,CAAC;AAEX,KAAK,UAAU,UAAU,CAAC,EAAE,UAAU,GAAG,gBAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAqB;IACjG,OAAO,MAAM,EAAE;SACZ,MAAM,CAAC;QACN,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,kBAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC;KACnC,CAAC;SACD,OAAO,EAAE,CAAC;AACf,CAAC;AARD,gCAQC","sourcesContent":["import AWS from 'aws-sdk';\nimport fs from 'fs-extra';\nimport _ from 'lodash';\n\nimport config from 'turtle/config';\n\ninterface IFileUploadParams {\n bucketName?: string;\n key: string;\n srcPath: string;\n}\n\nconst s3 = new AWS.S3({\n ..._.pick(config.aws, ['accessKeyId', 'secretAccessKey']),\n ..._.pick(config.s3, ['region']),\n});\n\nexport default s3;\n\nexport async function uploadFile({ bucketName = config.s3.bucket, key, srcPath }: IFileUploadParams) {\n return await s3\n .upload({\n Bucket: bucketName,\n Key: key,\n Body: fs.createReadStream(srcPath),\n })\n .promise();\n}\n"]}
+95
View File
@@ -0,0 +1,95 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const async_retry_1 = __importDefault(require("async-retry"));
const aws_sdk_1 = __importDefault(require("aws-sdk"));
const lodash_1 = __importDefault(require("lodash"));
const utils_1 = require("./utils");
const config_1 = __importDefault(require("../config"));
const logger_1 = __importDefault(require("../logger"));
const turtleContext_1 = require("../turtleContext");
const sqs = new aws_sdk_1.default.SQS({
apiVersion: '2012-11-05',
...lodash_1.default.pick(config_1.default.aws, ['accessKeyId', 'secretAccessKey']),
...lodash_1.default.pick(config_1.default.sqs, ['region']),
});
const VISIBILITY_TIMEOUT_SEC = 30;
async function receiveMessage(priority) {
const params = {
MaxNumberOfMessages: 1,
QueueUrl: utils_1.QUEUE_URL(priority),
VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,
};
return await async_retry_1.default(() => {
return sqs
.receiveMessage(params)
.promise()
.then((data) => {
if (data.Messages) {
logger_1.default.info(`Received a message`);
return data.Messages[0];
}
else {
logger_1.default.debug(`No messages received [${priority}]`);
return null;
}
})
.catch((err) => {
logger_1.default.error({ err }, 'Receive error');
throw err;
});
});
}
exports.receiveMessage = receiveMessage;
async function deleteMessage(priority, receiptHandle) {
const params = {
QueueUrl: utils_1.QUEUE_URL(priority),
ReceiptHandle: receiptHandle,
};
return await async_retry_1.default(() => {
return sqs.deleteMessage(params).promise();
});
}
exports.deleteMessage = deleteMessage;
async function changeMessageVisibility(priority, receiptHandle) {
const params = {
QueueUrl: utils_1.QUEUE_URL(priority),
ReceiptHandle: receiptHandle,
VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,
};
return sqs.changeMessageVisibility(params).promise();
}
exports.changeMessageVisibility = changeMessageVisibility;
// Every VISIBILITY_TIMEOUT_SEC / 3 seconds we are telling AWS SQS
// that we're still processing the message, so it does not
// send the build job to another turtle agent
function changeMessageVisibilityRecurring(priority, receiptHandle, jobId) {
return setInterval(() => {
if (turtleContext_1.getCurrentJobId() === jobId) {
changeMessageVisibility(priority, receiptHandle).catch((err) => {
logger_1.default.warn({ err }, 'Error at change msg visibility');
});
}
}, (VISIBILITY_TIMEOUT_SEC * 1000) / 3);
}
exports.changeMessageVisibilityRecurring = changeMessageVisibilityRecurring;
async function sendMessage(jobId, status, data = {}) {
const params = {
MessageBody: JSON.stringify({ jobId, status, ...data }),
QueueUrl: utils_1.OUTPUT_QUEUE_URL(),
DelaySeconds: 0,
MessageGroupId: jobId,
};
try {
return await async_retry_1.default(async () => {
return await sqs.sendMessage(params).promise();
});
}
catch (err) {
logger_1.default.error({ err }, `Error sending SQS message: ${JSON.stringify(params)}}`);
}
}
exports.sendMessage = sendMessage;
//# sourceMappingURL=sqs.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sqs.js","sourceRoot":"","sources":["../../src/aws/sqs.ts"],"names":[],"mappings":"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","sourcesContent":["import retry from 'async-retry';\nimport AWS from 'aws-sdk';\nimport _ from 'lodash';\n\nimport { OUTPUT_QUEUE_URL, QUEUE_URL } from 'turtle/aws/utils';\nimport config from 'turtle/config';\nimport { JOB_UPDATE_TYPE } from 'turtle/constants/build';\nimport logger from 'turtle/logger';\nimport { getCurrentJobId } from 'turtle/turtleContext';\n\nconst sqs = new AWS.SQS({\n apiVersion: '2012-11-05',\n ..._.pick(config.aws, ['accessKeyId', 'secretAccessKey']),\n ..._.pick(config.sqs, ['region']),\n});\n\nconst VISIBILITY_TIMEOUT_SEC = 30;\n\nexport async function receiveMessage(priority: string) {\n const params = {\n MaxNumberOfMessages: 1,\n QueueUrl: QUEUE_URL(priority),\n VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,\n };\n return await retry(() => {\n return sqs\n .receiveMessage(params)\n .promise()\n .then((data) => {\n if (data.Messages) {\n logger.info(`Received a message`);\n return data.Messages[0];\n } else {\n logger.debug(`No messages received [${priority}]`);\n return null;\n }\n })\n .catch((err) => {\n logger.error({ err }, 'Receive error');\n throw err;\n });\n });\n}\n\nexport async function deleteMessage(priority: string, receiptHandle: string) {\n const params = {\n QueueUrl: QUEUE_URL(priority),\n ReceiptHandle: receiptHandle,\n };\n return await retry(() => {\n return sqs.deleteMessage(params).promise();\n });\n}\n\nexport async function changeMessageVisibility(priority: string, receiptHandle: string) {\n const params = {\n QueueUrl: QUEUE_URL(priority),\n ReceiptHandle: receiptHandle,\n VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,\n };\n return sqs.changeMessageVisibility(params).promise();\n}\n\n// Every VISIBILITY_TIMEOUT_SEC / 3 seconds we are telling AWS SQS\n// that we're still processing the message, so it does not\n// send the build job to another turtle agent\nexport function changeMessageVisibilityRecurring(priority: string, receiptHandle: string, jobId: string) {\n return setInterval(() => {\n if (getCurrentJobId() === jobId) {\n changeMessageVisibility(priority, receiptHandle).catch((err) => {\n logger.warn({ err }, 'Error at change msg visibility');\n });\n }\n }, (VISIBILITY_TIMEOUT_SEC * 1000) / 3);\n}\n\nexport async function sendMessagLine truncated
+9
View File
@@ -0,0 +1,9 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = __importDefault(require("../config"));
exports.QUEUE_URL = (priority) => config_1.default.sqs.queues[priority][config_1.default.platform];
exports.OUTPUT_QUEUE_URL = () => config_1.default.sqs.queues.out;
//# sourceMappingURL=utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/aws/utils.ts"],"names":[],"mappings":";;;;;AAAA,uDAAmC;AAEtB,QAAA,SAAS,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAE,gBAAM,CAAC,GAAG,CAAC,MAAc,CAAC,QAAQ,CAAC,CAAC,gBAAM,CAAC,QAAQ,CAAC,CAAC;AACxF,QAAA,gBAAgB,GAAG,GAAG,EAAE,CAAC,gBAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC","sourcesContent":["import config from 'turtle/config';\n\nexport const QUEUE_URL = (priority: string) => (config.sqs.queues as any)[priority][config.platform];\nexport const OUTPUT_QUEUE_URL = () => config.sqs.queues.out;\n"]}
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ErrorWithCommandHelp extends Error {
}
exports.ErrorWithCommandHelp = ErrorWithCommandHelp;
//# sourceMappingURL=ErrorWithCommandHelp.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ErrorWithCommandHelp.js","sourceRoot":"","sources":["../../../src/bin/commands/ErrorWithCommandHelp.ts"],"names":[],"mappings":";;AAAA,MAAa,oBAAqB,SAAQ,KAAK;CAC9C;AADD,oDACC","sourcesContent":["export class ErrorWithCommandHelp extends Error {\n}\n"]}
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ErrorWithProgramHelp extends Error {
}
exports.ErrorWithProgramHelp = ErrorWithProgramHelp;
//# sourceMappingURL=ErrorWithProgramHelp.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ErrorWithProgramHelp.js","sourceRoot":"","sources":["../../../src/bin/commands/ErrorWithProgramHelp.ts"],"names":[],"mappings":";;AAAA,MAAa,oBAAqB,SAAQ,KAAK;CAC9C;AADD,oDACC","sourcesContent":["export class ErrorWithProgramHelp extends Error {\n}\n"]}
+55
View File
@@ -0,0 +1,55 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const ErrorWithCommandHelp_1 = require("../ErrorWithCommandHelp");
const builder_1 = require("../../utils/builder");
const android_1 = __importDefault(require("../../../builders/android"));
const constants_1 = require("../../../constants");
exports.default = (program, setCommonCommandOptions) => {
const command = program.command('build:android [project-dir]');
setCommonCommandOptions(command);
command
.alias('ba')
.option('--keystore-path <app.jks>', 'path to your Keystore (please provide Keystore password and Key password as EXPO_ANDROID_KEYSTORE_PASSWORD'
+ ' and EXPO_ANDROID_KEY_PASSWORD env variables)')
.option('--keystore-alias <alias>', 'keystore Alias')
.option('-t --type <build>', 'type of build: app-bundle|apk', /^(app-bundle|apk)$/i, 'app-bundle')
.option('-m --mode <build>', 'type of build: debug|release', /^(debug|release)$/i, 'release')
.description('Build a standalone APK or App Bundle for your project, either signed and ready for submission to'
+ ' the Google Play Store or in debug mode.')
.asyncAction(builder_1.createBuilderAction({
program,
command,
prepareCredentials,
builder: android_1.default,
platform: constants_1.PLATFORMS.ANDROID,
os: ['darwin', 'linux'],
}));
};
const prepareCredentials = async (cmd) => {
const { keystorePath, keystoreAlias } = cmd;
const keystorePassword = process.env.EXPO_ANDROID_KEYSTORE_PASSWORD;
const keyPassword = process.env.EXPO_ANDROID_KEY_PASSWORD;
const someCredentialsExist = keystorePath || keystoreAlias || keystorePassword || keyPassword;
const credentialsExist = keystorePath && keystoreAlias && keystorePassword && keyPassword;
if (!credentialsExist) {
if (someCredentialsExist) {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('Please provide all required credentials - Keystore (with password), Keystore alias and Key password');
}
else {
return null;
}
}
else {
return {
keystore: (await fs_extra_1.default.readFile(keystorePath)).toString('base64'),
keystoreAlias,
keystorePassword,
keyPassword,
};
}
};
//# sourceMappingURL=android.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"android.js","sourceRoot":"","sources":["../../../../src/bin/commands/build/android.ts"],"names":[],"mappings":";;;;;AAAA,wDAA0B;AAG1B,kEAAgF;AAChF,iDAA+D;AAC/D,wEAA8C;AAC9C,kDAA6C;AAE7C,kBAAe,CAAC,OAAY,EAAE,uBAA4B,EAAE,EAAE;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAC/D,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO;SACJ,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CACL,2BAA2B,EAC3B,4GAA4G;UAC1G,+CAA+C,CAClD;SACA,MAAM,CAAC,0BAA0B,EAAE,gBAAgB,CAAC;SACpD,MAAM,CACL,mBAAmB,EACnB,+BAA+B,EAC/B,qBAAqB,EACrB,YAAY,CACb;SACA,MAAM,CACL,mBAAmB,EACnB,8BAA8B,EAC9B,oBAAoB,EACpB,SAAS,CACV;SACA,WAAW,CACV,kGAAkG;UAChG,0CAA0C,CAC7C;SACA,WAAW,CACV,6BAAmB,CAAC;QAClB,OAAO;QACP,OAAO;QACP,kBAAkB;QAClB,OAAO,EAAP,iBAAO;QACP,QAAQ,EAAE,qBAAS,CAAC,OAAO;QAC3B,EAAE,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;KACxB,CAAC,CACH,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,GAAQ,EAAE,EAAE;IAC5C,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IAC5C,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC;IACpE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAE1D,MAAM,oBAAoB,GAAG,YAAY,IAAI,aAAa,IAAI,gBAAgB,IAAI,WAAW,CAAC;IAC9F,MAAM,gBAAgB,GAAG,YAAY,IAAI,aAAa,IAAI,gBAAgB,IAAI,WAAW,CAAC;IAC1F,IAAI,CAAC,gBAAgB,EAAE;QACrB,IAAI,oBAAoB,EAAE;YACxB,MAAM,IAAI,2CAAoB,CAC5B,qGAAqG,CACtG,CAAC;SACH;aAAM;YACL,OAAO,IAAI,CAAC;SACb;KACF;SAAM;QACL,OAAO;YACL,QAAQ,EAAE,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC9D,aAAa;YACb,gBAAgB;YAChB,WAAW;SACZ,CAAC;KACH;AACH,CAAC,CAAC","sourcesContent":["import fs from 'fs-extra';\nimport _ from 'lodash';\n\nimport { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';\nimport { createBuilderAction } from 'turtle/bin/utils/builder';\nimport builder from 'turtle/builders/android';\nimport { PLATFORMS } from 'turtle/constants';\n\nexport default (program: any, setCommonCommandOptions: any) => {\n const command = program.command('build:android [project-dir]');\n setCommonCommandOptions(command);\n command\n .alias('ba')\n .option(\n '--keystore-path <app.jks>',\n 'path to your Keystore (please provide Keystore password and Key password as EXPO_ANDROID_KEYSTORE_PASSWORD'\n + ' and EXPO_ANDROID_KEY_PASSWORD env variables)',\n )\n .option('--keystore-alias <alias>', 'keystore Alias')\n .option(\n '-t --type <build>',\n 'type of build: app-bundle|apk',\n /^(app-bundle|apk)$/i,\n 'app-bundle',\n )\n .option(\n '-m --mode <build>',\n 'type of build: debug|release',\n /^(debug|release)$/i,\n 'release',\n )\n .description(\n 'Build a standalone APK or App Bundle for your project, either signed and ready for submission to'\n + ' the Google Play Store or in debug mode.',\n )\n .asyncAction(\n createBuilderAction({\n program,\n command,\n prepareCredentials,\n builder,\n platform: PLATFORMS.ANDROID,\n os: ['darwin', 'linux'],\n }),\n );\n};\n\nconst prepareCredentials = async (cmd: any) => {\n const { keystorePath, keystoreAlias } = cmd;\n const keystorePassword = process.env.EXPO_ANDROID_KEYSTORE_PASSWORD;\n const keyPassword = process.env.EXPO_ANDROID_KEY_PASSWORD;\n\n const someCredentialsExist = keystorePath || keystoreAlias || keystorePassword || keyPassword;\n const credentialsExist = keystorePath && keystoreAlias && keystorePassword && keyPassword;\n if (!credentialsExist) {\n if (someCredentialsExist) {\n throw new ErrorWithCommandHelp(\n 'Please provide all required credentials - Keystore (with password), Keystore alias and Key password',\n );\n } else {\n return null;\n }\n } else {\n return {\n keystore: (await fs.readFile(keystorePath)).toString('base64'),\n keystoreAlias,\n keystorePassword,\n keyPassword,\n };\n }\n};\n"]}
+27
View File
@@ -0,0 +1,27 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const android_1 = __importDefault(require("./android"));
const ios_1 = __importDefault(require("./ios"));
function createCommand(builder) {
return (program) => {
return builder(program, setCommonCommandOptions);
};
}
function setCommonCommandOptions(cmd) {
cmd
.option('-u --username <username>', 'username (you can also set EXPO_USERNAME env variable)')
.option('-p --password <password>', 'password (you can also set EXPO_PASSWORD env variable)')
.option('-d --build-dir <build-dir>', 'directory for build artifact (default: `~/expo-apps`)')
.option('-o --output <output-file-path>', 'output file path')
.option('--public-url <url>', 'the URL of an externally hosted manifest (for self-hosted apps), only HTTPS URLs are supported!')
.option('--release-channel <channel-name>', 'pull from specified release channel (default: default)')
.option('-c --config <config-file>', 'specify a path to app.json');
}
exports.default = {
ios: createCommand(ios_1.default),
android: createCommand(android_1.default),
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/commands/build/index.ts"],"names":[],"mappings":";;;;;AAAA,wDAA4E;AAC5E,gDAAoE;AAEpE,SAAS,aAAa,CAAC,OAAY;IACjC,OAAO,CAAC,OAAY,EAAE,EAAE;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,GAAQ;IACvC,GAAG;SACA,MAAM,CAAC,0BAA0B,EAAE,wDAAwD,CAAC;SAC5F,MAAM,CAAC,0BAA0B,EAAE,wDAAwD,CAAC;SAC5F,MAAM,CAAC,4BAA4B,EAAE,uDAAuD,CAAC;SAC7F,MAAM,CAAC,gCAAgC,EAAE,kBAAkB,CAAC;SAC5D,MAAM,CACL,oBAAoB,EACpB,iGAAiG,CAClG;SACA,MAAM,CACL,kCAAkC,EAClC,wDAAwD,CACzD;SACA,MAAM,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,CAAC;AACvE,CAAC;AAED,kBAAe;IACb,GAAG,EAAE,aAAa,CAAC,aAAQ,CAAC;IAC5B,OAAO,EAAE,aAAa,CAAC,iBAAY,CAAC;CACrC,CAAC","sourcesContent":["import { default as buildAndroid } from 'turtle/bin/commands/build/android';\nimport { default as buildIOS } from 'turtle/bin/commands/build/ios';\n\nfunction createCommand(builder: any) {\n return (program: any) => {\n return builder(program, setCommonCommandOptions);\n };\n}\n\nfunction setCommonCommandOptions(cmd: any) {\n cmd\n .option('-u --username <username>', 'username (you can also set EXPO_USERNAME env variable)')\n .option('-p --password <password>', 'password (you can also set EXPO_PASSWORD env variable)')\n .option('-d --build-dir <build-dir>', 'directory for build artifact (default: `~/expo-apps`)')\n .option('-o --output <output-file-path>', 'output file path')\n .option(\n '--public-url <url>',\n 'the URL of an externally hosted manifest (for self-hosted apps), only HTTPS URLs are supported!',\n )\n .option(\n '--release-channel <channel-name>',\n 'pull from specified release channel (default: default)',\n )\n .option('-c --config <config-file>', 'specify a path to app.json');\n}\n\nexport default {\n ios: createCommand(buildIOS),\n android: createCommand(buildAndroid),\n};\n"]}
+48
View File
@@ -0,0 +1,48 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const ErrorWithCommandHelp_1 = require("../ErrorWithCommandHelp");
const builder_1 = require("../../utils/builder");
const ios_1 = __importDefault(require("../../../builders/ios"));
const constants_1 = require("../../../constants");
exports.default = (program, setCommonCommandOptions) => {
const command = program.command('build:ios [project-dir]');
setCommonCommandOptions(command);
command
.alias('bi')
.option('-t --type <build>', 'type of build: archive|simulator', /^(archive|simulator)$/i, 'archive')
.option('--team-id <apple-teamId>', 'Apple Team ID')
.option('--dist-p12-path <dist.p12>', 'path to your Distribution Certificate P12 (please provide password as EXPO_IOS_DIST_P12_PASSWORD env variable)')
.option('--provisioning-profile-path <.mobileprovision>', 'path to your Provisioning Profile')
.description('Build a standalone IPA for your project, signed and ready for submission to the Apple App Store.')
.asyncAction(builder_1.createBuilderAction({
program,
command,
prepareCredentials,
builder: ios_1.default,
platform: constants_1.PLATFORMS.IOS,
os: 'darwin',
}));
};
const prepareCredentials = async (cmd) => {
if (cmd.type !== constants_1.IOS_BUILD_TYPES.ARCHIVE) {
return null;
}
const { teamId, distP12Path, provisioningProfilePath } = cmd;
const certPassword = process.env.EXPO_IOS_DIST_P12_PASSWORD;
const credentialsExist = teamId && distP12Path && certPassword && provisioningProfilePath;
if (!credentialsExist) {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('Please provide all required credentials'
+ '- Apple Team ID, Distribution Certificate P12 (with password) and Provisioning Profile');
}
return {
teamId,
certP12: (await fs_extra_1.default.readFile(distP12Path)).toString('base64'),
certPassword,
provisioningProfile: (await fs_extra_1.default.readFile(provisioningProfilePath)).toString('base64'),
};
};
//# sourceMappingURL=ios.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ios.js","sourceRoot":"","sources":["../../../../src/bin/commands/build/ios.ts"],"names":[],"mappings":";;;;;AAAA,wDAA0B;AAG1B,kEAAgF;AAChF,iDAA+D;AAC/D,gEAA0C;AAC1C,kDAA8D;AAE9D,kBAAe,CAAC,OAAY,EAAE,uBAA4B,EAAE,EAAE;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC3D,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO;SACJ,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CACL,mBAAmB,EACnB,kCAAkC,EAClC,wBAAwB,EACxB,SAAS,CACV;SACA,MAAM,CAAC,0BAA0B,EAAE,eAAe,CAAC;SACnD,MAAM,CACL,4BAA4B,EAC5B,gHAAgH,CACjH;SACA,MAAM,CAAC,gDAAgD,EAAE,mCAAmC,CAAC;SAC7F,WAAW,CACV,kGAAkG,CACnG;SACA,WAAW,CACV,6BAAmB,CAAC;QAClB,OAAO;QACP,OAAO;QACP,kBAAkB;QAClB,OAAO,EAAP,aAAO;QACP,QAAQ,EAAE,qBAAS,CAAC,GAAG;QACvB,EAAE,EAAE,QAAQ;KACb,CAAC,CACH,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,GAAQ,EAAE,EAAE;IAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,2BAAe,CAAC,OAAO,EAAE;QACxC,OAAO,IAAI,CAAC;KACb;IAED,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,uBAAuB,EAAE,GAAG,GAAG,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IAE5D,MAAM,gBAAgB,GACpB,MAAM,IAAI,WAAW,IAAI,YAAY,IAAI,uBAAuB,CAAC;IAEnE,IAAI,CAAC,gBAAgB,EAAE;QACrB,MAAM,IAAI,2CAAoB,CAC5B,yCAAyC;cACvC,wFAAwF,CAC3F,CAAC;KACH;IAED,OAAO;QACL,MAAM;QACN,OAAO,EAAE,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC5D,YAAY;QACZ,mBAAmB,EAAE,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;KACrF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import fs from 'fs-extra';\nimport _ from 'lodash';\n\nimport { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';\nimport { createBuilderAction } from 'turtle/bin/utils/builder';\nimport builder from 'turtle/builders/ios';\nimport { IOS_BUILD_TYPES, PLATFORMS } from 'turtle/constants';\n\nexport default (program: any, setCommonCommandOptions: any) => {\n const command = program.command('build:ios [project-dir]');\n setCommonCommandOptions(command);\n command\n .alias('bi')\n .option(\n '-t --type <build>',\n 'type of build: archive|simulator',\n /^(archive|simulator)$/i,\n 'archive',\n )\n .option('--team-id <apple-teamId>', 'Apple Team ID')\n .option(\n '--dist-p12-path <dist.p12>',\n 'path to your Distribution Certificate P12 (please provide password as EXPO_IOS_DIST_P12_PASSWORD env variable)',\n )\n .option('--provisioning-profile-path <.mobileprovision>', 'path to your Provisioning Profile')\n .description(\n 'Build a standalone IPA for your project, signed and ready for submission to the Apple App Store.',\n )\n .asyncAction(\n createBuilderAction({\n program,\n command,\n prepareCredentials,\n builder,\n platform: PLATFORMS.IOS,\n os: 'darwin',\n }),\n );\n};\n\nconst prepareCredentials = async (cmd: any) => {\n if (cmd.type !== IOS_BUILD_TYPES.ARCHIVE) {\n return null;\n }\n\n const { teamId, distP12Path, provisioningProfilePath } = cmd;\n const certPassword = process.env.EXPO_IOS_DIST_P12_PASSWORD;\n\n const credentialsExist =\n teamId && distP12Path && certPassword && provisioningProfilePath;\n\n if (!credentialsExist) {\n throw new ErrorWithCommandHelp(\n 'Please provide all required credentials'\n + '- Apple Team ID, Distribution Certificate P12 (with password) and Provisioning Profile',\n );\n }\n\n return {\n teamId,\n certP12: (await fs.readFile(distP12Path)).toString('base64'),\n certPassword,\n provisioningProfile: (await fs.readFile(provisioningProfilePath)).toString('base64'),\n };\n};\n"]}
+12
View File
@@ -0,0 +1,12 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const build_1 = __importDefault(require("./build"));
const setup_1 = __importDefault(require("./setup"));
exports.setupIOS = setup_1.default.ios;
exports.setupAndroid = setup_1.default.android;
exports.buildIOS = build_1.default.ios;
exports.buildAndroid = build_1.default.android;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bin/commands/index.ts"],"names":[],"mappings":";;;;;AAAA,oDAAiD;AACjD,oDAA8C;AAEjC,QAAA,QAAQ,GAAG,eAAK,CAAC,GAAG,CAAC;AACrB,QAAA,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC;AAE7B,QAAA,QAAQ,GAAG,eAAQ,CAAC,GAAG,CAAC;AACxB,QAAA,YAAY,GAAG,eAAQ,CAAC,OAAO,CAAC","sourcesContent":["import builders from 'turtle/bin/commands/build';\nimport setup from 'turtle/bin/commands/setup';\n\nexport const setupIOS = setup.ios;\nexport const setupAndroid = setup.android;\n\nexport const buildIOS = builders.ios;\nexport const buildAndroid = builders.android;\n"]}
+48
View File
@@ -0,0 +1,48 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = __importDefault(require("lodash"));
const ErrorWithCommandHelp_1 = require("./ErrorWithCommandHelp");
const ErrorWithProgramHelp_1 = require("./ErrorWithProgramHelp");
const setup_1 = __importDefault(require("../setup/setup"));
const constants_1 = require("../../constants");
const logger_1 = __importDefault(require("../../logger"));
const l = logger_1.default.child({ buildPhase: 'setting up environment' });
function createSetupCommand(platform, os) {
return (program) => {
const command = program.command(`setup:${platform}`);
const platformFirstLetter = platform[0];
command
.alias(`s${platformFirstLetter}`)
.description(`Setup environment for building ${lodash_1.default.capitalize(platform)} standalone apps.`)
.option('--sdk-version <sdk-version>', 'version of Expo SDK shell app to download (optional)')
.asyncAction(async (cmd) => await setupAction(program, cmd, platform, os));
};
}
async function setupAction(program, cmd, platform, os) {
try {
if (os && process.platform !== os) {
throw new Error('We don\'t support running standalone app builds for this platform on your operating system');
}
const { sdkVersion } = cmd;
await setup_1.default(platform, sdkVersion);
l.info('it\'s all set!');
}
catch (err) {
logger_1.default.error({ err }, `Failed to setup environment for ${platform} builds`);
if (err instanceof ErrorWithCommandHelp_1.ErrorWithCommandHelp) {
cmd.help();
}
else if (err instanceof ErrorWithProgramHelp_1.ErrorWithProgramHelp) {
program.help();
}
process.exit(1);
}
}
exports.default = {
ios: createSetupCommand(constants_1.PLATFORMS.IOS, 'darwin'),
android: createSetupCommand(constants_1.PLATFORMS.ANDROID),
};
//# sourceMappingURL=setup.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/bin/commands/setup.ts"],"names":[],"mappings":";;;;;AAAA,oDAAuB;AAEvB,iEAAgF;AAChF,iEAAgF;AAChF,2DAA2C;AAC3C,+CAA6C;AAC7C,0DAAmC;AAEnC,MAAM,CAAC,GAAG,gBAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAEjE,SAAS,kBAAkB,CAAC,QAAgB,EAAE,EAAW;IACvD,OAAO,CAAC,OAAY,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;QACrD,MAAM,mBAAmB,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO;aACJ,KAAK,CAAC,IAAI,mBAAmB,EAAE,CAAC;aAChC,WAAW,CAAC,kCAAkC,gBAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC;aACxF,MAAM,CACL,6BAA6B,EAC7B,sDAAsD,CACvD;aACA,WAAW,CAAC,KAAK,EAAE,GAAQ,EAAE,EAAE,CAAC,MAAM,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IACpF,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAY,EAAE,GAAQ,EAAE,QAAgB,EAAE,EAAW;IAC9E,IAAI;QACF,IAAI,EAAE,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAC;SAC/G;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;QAC3B,MAAM,eAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;KAC1B;IAAC,OAAO,GAAG,EAAE;QACZ,gBAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,mCAAmC,QAAQ,SAAS,CAAC,CAAC;QAC5E,IAAI,GAAG,YAAY,2CAAoB,EAAE;YACvC,GAAG,CAAC,IAAI,EAAE,CAAC;SACZ;aAAM,IAAI,GAAG,YAAY,2CAAoB,EAAE;YAC9C,OAAO,CAAC,IAAI,EAAE,CAAC;SAChB;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;AACH,CAAC;AAED,kBAAe;IACb,GAAG,EAAE,kBAAkB,CAAC,qBAAS,CAAC,GAAG,EAAE,QAAQ,CAAC;IAChD,OAAO,EAAE,kBAAkB,CAAC,qBAAS,CAAC,OAAO,CAAC;CAC/C,CAAC","sourcesContent":["import _ from 'lodash';\n\nimport { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';\nimport { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';\nimport setup from 'turtle/bin/setup/setup';\nimport { PLATFORMS } from 'turtle/constants';\nimport logger from 'turtle/logger';\n\nconst l = logger.child({ buildPhase: 'setting up environment' });\n\nfunction createSetupCommand(platform: string, os?: string) {\n return (program: any) => {\n const command = program.command(`setup:${platform}`);\n const platformFirstLetter = platform[0];\n command\n .alias(`s${platformFirstLetter}`)\n .description(`Setup environment for building ${_.capitalize(platform)} standalone apps.`)\n .option(\n '--sdk-version <sdk-version>',\n 'version of Expo SDK shell app to download (optional)',\n )\n .asyncAction(async (cmd: any) => await setupAction(program, cmd, platform, os));\n };\n}\n\nasync function setupAction(program: any, cmd: any, platform: string, os?: string) {\n try {\n if (os && process.platform !== os) {\n throw new Error('We don\\'t support running standalone app builds for this platform on your operating system');\n }\n\n const { sdkVersion } = cmd;\n await setup(platform, sdkVersion);\n l.info('it\\'s all set!');\n } catch (err) {\n logger.error({ err }, `Failed to setup environment for ${platform} builds`);\n if (err instanceof ErrorWithCommandHelp) {\n cmd.help();\n } else if (err instanceof ErrorWithProgramHelp) {\n program.help();\n }\n process.exit(1);\n }\n}\n\nexport default {\n ios: createSetupCommand(PLATFORMS.IOS, 'darwin'),\n android: createSetupCommand(PLATFORMS.ANDROID),\n};\n"]}
+53
View File
@@ -0,0 +1,53 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const lodash_1 = __importDefault(require("lodash"));
const env_1 = require("../utils/env");
const resolveEnv = () => {
if (env_1.env('EXPO_LOCAL', '0') === '1') {
return 'local';
}
else if (env_1.env('EXPO_STAGING', '0') === '1') {
return 'staging';
}
else {
return 'production';
}
};
const currentEnv = resolveEnv();
const isLocal = (envName) => envName === 'local';
const isStaging = (envName) => envName === 'staging';
const apiConfig = {
protocol: 'https',
hostname: 'exp.host',
port: 443,
};
if (isStaging(currentEnv)) {
apiConfig.hostname = 'staging.exp.host';
}
else if (isLocal(currentEnv)) {
apiConfig.protocol = 'http';
apiConfig.hostname = 'localhost';
apiConfig.port = 3000;
}
const OFFLINE_ENV_VARS = {
TURTLE_MODE: 'offline',
API_PROTOCOL: apiConfig.protocol,
API_HOSTNAME: apiConfig.hostname,
API_PORT: apiConfig.port,
TURTLE_FAKE_UPLOAD: '1',
TURTLE_FAKE_UPLOAD_DIR: path_1.default.join(os_1.default.homedir(), 'expo-apps'),
TURTLE_WORKING_DIR_PATH: path_1.default.join(os_1.default.homedir(), '.turtle/workingdir'),
EXPO_SKIP_SOURCING: '1',
};
function initOfflineEnv() {
lodash_1.default.map(OFFLINE_ENV_VARS, (val, key) => {
process.env[key] = String(val);
});
}
exports.initOfflineEnv = initOfflineEnv;
//# sourceMappingURL=env.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/bin/env.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAExB,oDAAuB;AAEvB,sCAAuC;AAEvC,MAAM,UAAU,GAAG,GAAG,EAAE;IACtB,IAAI,SAAG,CAAC,YAAY,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE;QAClC,OAAO,OAAO,CAAC;KAChB;SAAM,IAAI,SAAG,CAAC,cAAc,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE;QAC3C,OAAO,SAAS,CAAC;KAClB;SAAM;QACL,OAAO,YAAY,CAAC;KACrB;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;AAChC,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC;AACzD,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC;AAE7D,MAAM,SAAS,GAAG;IAChB,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,GAAG;CACV,CAAC;AAEF,IAAI,SAAS,CAAC,UAAU,CAAC,EAAE;IACzB,SAAS,CAAC,QAAQ,GAAG,kBAAkB,CAAC;CACzC;KAAM,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE;IAC9B,SAAS,CAAC,QAAQ,GAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,QAAQ,GAAG,WAAW,CAAC;IACjC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,gBAAgB,GAAG;IACvB,WAAW,EAAE,SAAS;IACtB,YAAY,EAAE,SAAS,CAAC,QAAQ;IAChC,YAAY,EAAE,SAAS,CAAC,QAAQ;IAChC,QAAQ,EAAE,SAAS,CAAC,IAAI;IACxB,kBAAkB,EAAE,GAAG;IACvB,sBAAsB,EAAE,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC;IAC5D,uBAAuB,EAAE,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC;IACtE,kBAAkB,EAAE,GAAG;CACxB,CAAC;AAEF,SAAgB,cAAc;IAC5B,gBAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACnC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAJD,wCAIC","sourcesContent":["import os from 'os';\nimport path from 'path';\n\nimport _ from 'lodash';\n\nimport { env } from 'turtle/utils/env';\n\nconst resolveEnv = () => {\n if (env('EXPO_LOCAL', '0') === '1') {\n return 'local';\n } else if (env('EXPO_STAGING', '0') === '1') {\n return 'staging';\n } else {\n return 'production';\n }\n};\n\nconst currentEnv = resolveEnv();\nconst isLocal = (envName: string) => envName === 'local';\nconst isStaging = (envName: string) => envName === 'staging';\n\nconst apiConfig = {\n protocol: 'https',\n hostname: 'exp.host',\n port: 443,\n};\n\nif (isStaging(currentEnv)) {\n apiConfig.hostname = 'staging.exp.host';\n} else if (isLocal(currentEnv)) {\n apiConfig.protocol = 'http';\n apiConfig.hostname = 'localhost';\n apiConfig.port = 3000;\n}\n\nconst OFFLINE_ENV_VARS = {\n TURTLE_MODE: 'offline',\n API_PROTOCOL: apiConfig.protocol,\n API_HOSTNAME: apiConfig.hostname,\n API_PORT: apiConfig.port,\n TURTLE_FAKE_UPLOAD: '1',\n TURTLE_FAKE_UPLOAD_DIR: path.join(os.homedir(), 'expo-apps'),\n TURTLE_WORKING_DIR_PATH: path.join(os.homedir(), '.turtle/workingdir'),\n EXPO_SKIP_SOURCING: '1',\n};\n\nexport function initOfflineEnv() {\n _.map(OFFLINE_ENV_VARS, (val, key) => {\n process.env[key] = String(val);\n });\n}\n"]}
+71
View File
@@ -0,0 +1,71 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const commander_1 = __importStar(require("commander"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const commands = __importStar(require("./commands"));
const logger_1 = __importDefault(require("../logger"));
const { name, version } = JSON.parse(fs_extra_1.default.readFileSync(path_1.default.join(__dirname, '../../package.json'), 'utf-8'));
const ModuleVersionChecker = xdl_1.ModuleVersion.createModuleVersionChecker(name, version);
xdl_1.LoggerDetach.configure(logger_1.default);
commander_1.Command.prototype.asyncAction = function asyncAction(asyncFn) {
return this.action(async (...args) => {
try {
await checkForUpdateAsync();
}
catch (err) {
logger_1.default.warn({ err }, 'Failed to check for turtle-cli update.');
}
return await asyncFn(...args);
});
};
function run(programName) {
runAsync(programName).catch((err) => {
logger_1.default.error({ err }, 'Uncaught Error');
process.exit(1);
});
}
exports.run = run;
async function runAsync(programName) {
commander_1.default.version(version);
Object.values(commands).forEach((command) => registerCommand(commander_1.default, command));
commander_1.default.parse(process.argv);
const subCommand = process.argv[2];
if (subCommand) {
const commandNames = commander_1.default.commands.reduce((acc, command) => {
acc.push(command._name);
const alias = command._alias;
if (alias) {
acc.push(alias);
}
return acc;
}, []);
if (!commandNames.includes(subCommand)) {
logger_1.default.error(`"${subCommand}" is not an ${programName} command. See "${programName} --help" for the full list of commands.`);
}
}
else {
commander_1.default.help();
}
}
const registerCommand = (prog, command) => command(prog);
async function checkForUpdateAsync() {
const { updateIsAvailable, current, latest } = await ModuleVersionChecker.checkAsync();
if (updateIsAvailable) {
logger_1.default.warn(`There is a new version of ${name} available (${latest}).
You are currently using ${name} ${current}
Run \`npm install -g ${name}\` to get the latest version`);
}
}
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport { LoggerDetach, ModuleVersion } from '@expo/xdl';\nimport program, { Command } from 'commander';\nimport fs from 'fs-extra';\n\nimport * as commands from 'turtle/bin/commands';\nimport logger from 'turtle/logger';\n\nconst { name, version } = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));\n\nconst ModuleVersionChecker = ModuleVersion.createModuleVersionChecker(name, version);\n\nLoggerDetach.configure(logger);\n\nCommand.prototype.asyncAction = function asyncAction(asyncFn: (...asyncFnArgs: any[]) => void): Command {\n return this.action(async (...args) => {\n try {\n await checkForUpdateAsync();\n } catch (err) {\n logger.warn({ err }, 'Failed to check for turtle-cli update.');\n }\n return await asyncFn(...args);\n });\n};\n\nexport function run(programName: string) {\n runAsync(programName).catch((err) => {\n logger.error({ err }, 'Uncaught Error');\n process.exit(1);\n });\n}\n\nasync function runAsync(programName: string) {\n program.version(version);\n Object.values(commands).forEach((command) => registerCommand(program, command));\n program.parse(process.argv);\n\n const subCommand = process.argv[2];\n if (subCommand) {\n const commandNames = program.commands.reduce((acc: string[], command: any) => {\n acc.push(command._name);\n const alias = command._alias;\n if (alias) {\n acc.push(alias);\n }\n return acc;\n }, []);\n if (!commandNames.includes(subCommand)) {\n logger.error(\n `\"${subCommand}\" is not an ${programName} command. See \"${programName} --help\" for the full list of commands.`,\n );\n }\n } else {\n program.help();\n }\n}\n\nconst registerCommand = (prog: any, command: any) => command(prog);\n\nasync function checkForUpdateAsync() {\n const { updateIsAvailable, current, latest } = await ModuleVersionChecker.checkAsync();\n if (updateIsAvailable) {\n logger.warn(\n `There is a new version of ${name} available (${latest}).\nYou are currently using ${name} ${current}\nRun \\`npm install -g ${name}\\` to get the latest version`,\n );\n }\n}\n"]}
+116
View File
@@ -0,0 +1,116 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const util_1 = __importDefault(require("util"));
const xdl_1 = require("@expo/xdl");
const fs_extra_1 = __importDefault(require("fs-extra"));
const which_1 = __importDefault(require("which"));
const sdk_1 = __importDefault(require("./sdk"));
const common_1 = require("../utils/common");
const workingdir_1 = require("../../../builders/utils/android/workingdir");
const config_1 = __importDefault(require("../../../config"));
const constants_1 = require("../../../constants");
const logger_1 = __importDefault(require("../../../logger"));
const which = util_1.default.promisify(which_1.default);
const JAVA_REQUIRED_VERSION = 8;
const REQUIRED_TOOLS = [
{
command: 'bash',
missingDescription: 'Please install bash',
},
{
command: 'javac',
missingDescription: `Please install JDK 8 - keep in mind that other versions are not supported by Android`,
testFn: async () => {
const { status, stdout, stderr } = await xdl_1.ExponentTools.spawnAsyncThrowError('java', ['-version'], { stdio: 'pipe' });
if (stdout.match(/no java runtime present/i)) {
return false;
}
const matchResult = stderr.match(/.*version "(.*)"/);
if (matchResult) {
const [, currentFullJavaVersion] = matchResult;
const javaMajorVersionPosition = currentFullJavaVersion.startsWith('1.') ? 1 : 0;
const javaMajorVersion = Number(currentFullJavaVersion.split('.')[javaMajorVersionPosition]);
if (javaMajorVersion !== JAVA_REQUIRED_VERSION) {
throw new Error(`You're on Java ${currentFullJavaVersion}, please install version ${JAVA_REQUIRED_VERSION}`);
}
}
else {
logger_1.default.warn(`Couldn't find Java version number, assuming you're on Java ${JAVA_REQUIRED_VERSION}...`);
}
return status === 0;
},
},
];
const LOGGER_FIELDS = { buildPhase: 'setting up environment' };
const l = logger_1.default.child(LOGGER_FIELDS);
async function setup(sdkVersion) {
await common_1.checkSystem(REQUIRED_TOOLS);
await prepareAndroidEnv();
if (sdkVersion) {
await common_1.ensureShellAppIsPresent(sdkVersion, { formatShellAppDirectory: workingdir_1.formatShellAppDirectory, formatShellAppTarballUriPath }, _shellAppPostDownloadAction);
}
}
exports.default = setup;
async function prepareAndroidEnv() {
await fs_extra_1.default.ensureDir(config_1.default.directories.androidDependenciesDir);
const sdkConfig = await sdk_1.default();
_setEnvVars(sdkConfig.envVars);
_alterPath(sdkConfig.path);
}
function formatShellAppTarballUriPath(sdkMajorVersion) {
return path_1.default.join(config_1.default.directories.shellTarballsDir, constants_1.PLATFORMS.ANDROID, `sdk${sdkMajorVersion}`);
}
async function _shellAppPostDownloadAction(sdkVersion, workingdir) {
const inWorkingdir = (filename) => path_1.default.join(workingdir, filename);
if (await fs_extra_1.default.pathExists(inWorkingdir('universe-package.json'))) {
// legacy shell app built from universe
await fs_extra_1.default.move(inWorkingdir('package.json'), inWorkingdir('exponent-package.json'));
await fs_extra_1.default.move(inWorkingdir('universe-package.json'), inWorkingdir('package.json'));
await _installNodeModules(workingdir);
await fs_extra_1.default.move(inWorkingdir('package.json'), inWorkingdir('universe-package.json'));
await fs_extra_1.default.move(inWorkingdir('exponent-package.json'), inWorkingdir('package.json'));
}
else {
// new shell app built from expo or not
await _installNodeModules(workingdir);
}
// TODO: remove this after making sure that we don't need node_modules in tools-public for older sdks
if (xdl_1.ExponentTools.parseSdkMajorVersion(sdkVersion) < 33) {
const toolsPublicDir = path_1.default.join(workingdir, 'tools-public');
await _installNodeModules(toolsPublicDir);
}
}
async function _installNodeModules(cwd) {
l.info(`installing dependencies in ${cwd} directory...`);
const command = await _shouldUseYarnOrNpm();
await xdl_1.ExponentTools.spawnAsyncThrowError(command, ['install'], {
pipeToLogger: true,
loggerFields: LOGGER_FIELDS,
cwd,
});
l.info('dependencies installed!');
}
async function _shouldUseYarnOrNpm() {
try {
await which('yarn');
return 'yarn';
}
catch (err) {
return 'npm';
}
}
function _setEnvVars(envVars) {
Object
.entries(envVars)
.forEach(([key, value]) => process.env[key] = value);
}
function _alterPath(newPaths) {
const currentPaths = process.env.PATH ? process.env.PATH.split(':') : [];
const paths = [...newPaths, ...currentPaths];
process.env.PATH = paths.join(':');
}
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/setup/android/index.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport util from 'util';\n\nimport { ExponentTools } from '@expo/xdl';\nimport fs from 'fs-extra';\nimport _which from 'which';\n\nimport ensureAndroidSDKIsPresent from 'turtle/bin/setup/android/sdk';\nimport { checkSystem, ensureShellAppIsPresent } from 'turtle/bin/setup/utils/common';\nimport { IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';\nimport { formatShellAppDirectory } from 'turtle/builders/utils/android/workingdir';\nimport config from 'turtle/config';\nimport { PLATFORMS } from 'turtle/constants';\nimport logger from 'turtle/logger';\n\nconst which = util.promisify(_which);\nconst JAVA_REQUIRED_VERSION = 8;\nconst REQUIRED_TOOLS: IToolDefinition[] = [\n {\n command: 'bash',\n missingDescription: 'Please install bash',\n },\n {\n command: 'javac',\n missingDescription:\n `Please install JDK 8 - keep in mind that other versions are not supported by Android`,\n testFn: async () => {\n const { status, stdout, stderr } = await ExponentTools.spawnAsyncThrowError(\n 'java',\n ['-version'],\n { stdio: 'pipe' },\n Line truncated
+87
View File
@@ -0,0 +1,87 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const decompress_1 = __importDefault(require("decompress"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const utils = __importStar(require("../utils/common"));
const downloader_1 = __importDefault(require("../utils/downloader"));
const config_1 = __importDefault(require("../../../config"));
const logger_1 = __importDefault(require("../../../logger"));
const ANDROID_SDK_URL = 'https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip';
const LOGGER_FIELDS = { buildPhase: 'setting up environment' };
const l = logger_1.default.child(LOGGER_FIELDS);
async function ensureAndroidSDKIsPresent() {
const androidSdkDir = path_1.default.join(config_1.default.directories.androidDependenciesDir, 'sdk');
await utils.removeDirectoryUnlessReady(androidSdkDir);
if (!(await fs_extra_1.default.pathExists(androidSdkDir))) {
await fs_extra_1.default.ensureDir(androidSdkDir);
const androidSdkDownloadPath = utils.formatArtifactDownloadPath(ANDROID_SDK_URL);
try {
l.info('Downloading Android SDK');
await fs_extra_1.default.ensureDir(config_1.default.directories.artifactsDir);
await downloader_1.default(ANDROID_SDK_URL, androidSdkDownloadPath);
await fs_extra_1.default.ensureDir(androidSdkDir);
l.info('Decompressing Android SDK');
await decompress_1.default(androidSdkDownloadPath, androidSdkDir);
await fs_extra_1.default.remove(androidSdkDownloadPath);
l.info('Configuring Android SDK, this may take a while');
await _configureSdk(androidSdkDir);
await utils.markDirectoryAsReady(androidSdkDir);
l.info('Android SDK installed and configured successfully');
}
catch (err) {
await fs_extra_1.default.remove(androidSdkDir);
throw err;
}
finally {
await fs_extra_1.default.remove(androidSdkDownloadPath);
}
}
return {
envVars: _createEnvVars(androidSdkDir),
path: _createPaths(androidSdkDir),
};
}
exports.default = ensureAndroidSDKIsPresent;
async function _configureSdk(androidSdkDir) {
// prevents warnings about missing repo config
const androidRepositoriesCfgPath = path_1.default.join(os_1.default.homedir(), '.android/repositories.cfg');
await fs_extra_1.default.ensureFile(androidRepositoriesCfgPath);
await xdl_1.ExponentTools.spawnAsyncThrowError('./configureAndroidSdk.sh', [], {
pipeToLogger: true,
loggerFields: LOGGER_FIELDS,
cwd: path_1.default.join(config_1.default.directories.rootDir, 'scripts/android'),
env: {
...process.env,
ANDROID_HOME: androidSdkDir,
ANDROID_SDK: androidSdkDir,
},
});
}
function _createEnvVars(androidSdkDir) {
return {
ANDROID_HOME: androidSdkDir,
ANDROID_SDK: androidSdkDir,
};
}
function _createPaths(androidSdkDir) {
return [
path_1.default.join(androidSdkDir, 'platform-tools'),
path_1.default.join(androidSdkDir, 'tools'),
path_1.default.join(androidSdkDir, 'tools/bin'),
path_1.default.join(androidSdkDir, 'build-tools/28.0.3'),
];
}
//# sourceMappingURL=sdk.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../../../src/bin/setup/android/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'os';\nimport path from 'path';\n\nimport { ExponentTools } from '@expo/xdl';\nimport decompress from 'decompress';\nimport fs from 'fs-extra';\n\nimport * as utils from 'turtle/bin/setup/utils/common';\nimport download from 'turtle/bin/setup/utils/downloader';\nimport config from 'turtle/config';\nimport logger from 'turtle/logger';\n\nconst ANDROID_SDK_URL = 'https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip';\n\nconst LOGGER_FIELDS = { buildPhase: 'setting up environment' };\nconst l = logger.child(LOGGER_FIELDS);\n\nexport default async function ensureAndroidSDKIsPresent() {\n const androidSdkDir = path.join(config.directories.androidDependenciesDir, 'sdk');\n await utils.removeDirectoryUnlessReady(androidSdkDir);\n if (!(await fs.pathExists(androidSdkDir))) {\n await fs.ensureDir(androidSdkDir);\n const androidSdkDownloadPath = utils.formatArtifactDownloadPath(ANDROID_SDK_URL);\n\n try {\n l.info('Downloading Android SDK');\n await fs.ensureDir(config.directories.artifactsDir);\n await download(ANDROID_SDK_URL, androidSdkDownloadPath);\n await fs.ensureDir(androidSdkDir);\n l.info('Decompressing Android SDK');\n await decompress(androidSdkDownloadPath, androidSdkDir);\n await fs.remove(androidSdkDownloadPath);\n l.info('Configuring Android SDK, this may take a while');\n await _configureSdk(androidSdkDir);\n await utils.markDirectoryAsReady(androidSdkDir);\n l.info('Android SDK installed and configured successfully');\n } catch (err) {\n await fs.remove(androidSdkDir);\n throw err;\n } finally {\n await fs.remove(androidSdkDownloadPath);\n }\n }\n return {\n envVars: _createEnvVars(androidSdkDir),\n path: _createPaths(androidSdkDir),\n };\n}\n\nasync function _configureSdk(androidSdkDir: string) {\n // prevents warnings about missing repo config\n const androidRepositoriesCfgPath = path.join(os.homedir(), '.android/repositories.cfg');\n await fs.ensureFile(androidRepositoriesCfgPath);\n await ExponentTools.spawnAsyncThrowError('./configureAndroidSdk.sh', [], {\n pipeToLogger: true,\n loggerFields: LOGGER_FIELDS,\n cwd: path.join(config.directories.rootDir, 'scripts/android'),\n env: {\n ...process.env,\n ANDROID_HOME: androidSdkDir,\n ANDROID_SDK: androidSdkDir,\n },\n });\n}\n\nfunction _createEnvVars(androidSdkDir: string) {\n return {\n ANDROID_HOME: androidSdkDir,\n ANDROID_SDK: androidSdkDir,\n };\n}\n\nfunction _createPaths(androidSdkDir: string) {\n return [\n path.join(androidSdkDir, 'platform-toLine truncated
+84
View File
@@ -0,0 +1,84 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const last_1 = __importDefault(require("lodash/last"));
const trim_1 = __importDefault(require("lodash/trim"));
const path_1 = __importDefault(require("path"));
const semver_1 = __importDefault(require("semver"));
const xdl_1 = require("@expo/xdl");
const common_1 = require("./utils/common");
const workingdir_1 = require("../../builders/utils/ios/workingdir");
const config_1 = __importDefault(require("../../config"));
const constants_1 = require("../../constants");
const logger_1 = __importDefault(require("../../logger"));
const REQUIRED_TOOLS = [
{
command: 'bash',
missingDescription: 'Please install bash',
},
{
command: 'fastlane',
missingDescription: 'Please check https://docs.fastlane.tools/getting-started/ios/setup/',
versionCheckFn: async () => {
const MINIMAL_VERSION = '2.99.0';
const { stdout } = await xdl_1.ExponentTools.spawnAsyncThrowError('fastlane', ['--version'], { stdio: 'pipe', env: { ...process.env, FASTLANE_SKIP_UPDATE_CHECK: '1', LC_ALL: 'en_US.UTF-8' } });
const fastlaneVersion = parseFastlaneVersion(stdout);
if (fastlaneVersion && !semver_1.default.satisfies(fastlaneVersion, `>= ${MINIMAL_VERSION}`)) {
throw new Error(`Your fastlane is on version ${fastlaneVersion}. Please upgrade it to at least ${MINIMAL_VERSION}.`);
}
},
},
{
command: 'xcode',
missingDescription: 'Please ensure xcode is properly installed',
testFn: async () => {
const { status, stdout } = await xdl_1.ExponentTools.spawnAsyncThrowError('xcodebuild', ['-version'], { stdio: 'pipe' });
if (stdout.match(/requires xcode/i)) {
return false;
}
if (status !== 0) {
return false;
}
try {
await xdl_1.ExponentTools.spawnAsyncThrowError('ibtool', ['--version'], { stdio: 'pipe' });
}
catch (err) {
if (err.stderr) {
const stderr = err.stderr.trim();
if (stderr.match(/Agreeing to the Xcode\/iOS license/)) {
logger_1.default.error('You have not accepted the Xcode license. Run \'sudo xcodebuild -runFirstLaunch\' to do so.');
return false;
}
if (stderr.match(/The bundle is damaged or missing necessary resources/)) {
logger_1.default.error('Make sure to install additional required components. Run \'sudo xcodebuild -runFirstLaunch\' to do so.');
return false;
}
}
}
return true;
},
},
];
async function setup(sdkVersion) {
await common_1.checkSystem(REQUIRED_TOOLS);
if (sdkVersion) {
await common_1.ensureShellAppIsPresent(sdkVersion, {
formatShellAppDirectory: workingdir_1.formatShellAppDirectory,
formatShellAppTarballUriPath,
});
}
}
exports.default = setup;
function formatShellAppTarballUriPath(sdkMajorVersion) {
return path_1.default.join(config_1.default.directories.shellTarballsDir, constants_1.PLATFORMS.IOS, `sdk${sdkMajorVersion}`);
}
function parseFastlaneVersion(stdout) {
const lastLine = last_1.default(trim_1.default(stdout).split('\n'));
if (!lastLine) {
return null;
}
return last_1.default(lastLine.split(' ')) || null;
}
//# sourceMappingURL=ios.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ios.js","sourceRoot":"","sources":["../../../src/bin/setup/ios.ts"],"names":[],"mappings":"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","sourcesContent":["import last from 'lodash/last';\nimport trim from 'lodash/trim';\nimport path from 'path';\nimport semver from 'semver';\n\nimport { ExponentTools } from '@expo/xdl';\n\nimport { checkSystem, ensureShellAppIsPresent } from 'turtle/bin/setup/utils/common';\nimport { IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';\nimport { formatShellAppDirectory } from 'turtle/builders/utils/ios/workingdir';\nimport config from 'turtle/config';\nimport { PLATFORMS } from 'turtle/constants';\nimport logger from 'turtle/logger';\n\nconst REQUIRED_TOOLS: IToolDefinition[] = [\n {\n command: 'bash',\n missingDescription: 'Please install bash',\n },\n {\n command: 'fastlane',\n missingDescription: 'Please check https://docs.fastlane.tools/getting-started/ios/setup/',\n versionCheckFn: async () => {\n const MINIMAL_VERSION = '2.99.0';\n\n const { stdout } = await ExponentTools.spawnAsyncThrowError(\n 'fastlane',\n ['--version'],\n { stdio: 'pipe', env: { ...process.env, FASTLANE_SKIP_UPDATE_CHECK: '1', LC_ALL: 'en_US.UTF-8' } },\n );\n const fastlaneVersion = parseFastlaneVersion(stdout);\n if (fastlaneVersion && !semver.satisfies(fastlaneVersion, `>= ${MINIMAL_VERSION}`)) {\n throw new Error(\n `Your fastlane is on version ${fastlaneVersion}. Please upgrade it to at least ${MINIMAL_VERSION}.`,\n );\n }\n },\n },\n {\n command: 'xcode',\n missingDescription: 'Please ensure xcode is properly installed',\n testFn: async () => {\n const { status, stdout } = await ExponentTools.spawnAsyncThrowError(\n 'xcodebuild',\n ['-version'],\n { stdio: 'pipe' },\n );\n if (stdout.match(/requires xcode/i)) {\n return false;\n }\n\n if (status !== 0) {\n return false;\n }\n\n try {\n await ExponentTools.spawnAsyncThrowError('ibtool', ['--version'], { stdio: 'pipe' });\n } catch (err) {\n if (err.stderr) {\n const stderr = err.stderr.trim();\n if (stderr.match(/Agreeing to the Xcode\\/iOS license/)) {\n logger.error('You have not accepted the Xcode license. Run \\'sudo xcodebuild -runFirstLaunch\\' to do so.');\n return false;\n }\n if (stderr.match(/The bundle is damaged or missing necessary resources/)) {\n logger.error(\n 'Make sure to install additional required components. Run \\'sudo xcodebuild -runFirstLaunch\\' to do so.',\n );\n return false;\n }\n }\n }\n\n return true;\n },\n },\n];\n\nexport dLine truncated
+25
View File
@@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const is_semver_1 = __importDefault(require("is-semver"));
const android_1 = __importDefault(require("./android"));
const ios_1 = __importDefault(require("./ios"));
const constants_1 = require("../../constants");
async function setup(platform, sdkVersion) {
if (sdkVersion && !is_semver_1.default(sdkVersion)) {
throw new Error('SDK version is not valid.');
}
if (platform === constants_1.PLATFORMS.IOS) {
return await ios_1.default(sdkVersion);
}
else if (platform === constants_1.PLATFORMS.ANDROID) {
return await android_1.default(sdkVersion);
}
else {
throw new Error('This should never happen :(');
}
}
exports.default = setup;
//# sourceMappingURL=setup.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/bin/setup/setup.ts"],"names":[],"mappings":";;;;;AAAA,0DAAiC;AAEjC,wDAAoD;AACpD,gDAA4C;AAC5C,+CAA6C;AAE9B,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,UAAmB;IACvE,IAAI,UAAU,IAAI,CAAC,mBAAQ,CAAC,UAAU,CAAC,EAAE;QACvC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;KAC9C;IAED,IAAI,QAAQ,KAAK,qBAAS,CAAC,GAAG,EAAE;QAC9B,OAAO,MAAM,aAAQ,CAAC,UAAU,CAAC,CAAC;KACnC;SAAM,IAAI,QAAQ,KAAK,qBAAS,CAAC,OAAO,EAAE;QACzC,OAAO,MAAM,iBAAY,CAAC,UAAU,CAAC,CAAC;KACvC;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;KAChD;AACH,CAAC;AAZD,wBAYC","sourcesContent":["import isSemver from 'is-semver';\n\nimport setupAndroid from 'turtle/bin/setup/android';\nimport setupIos from 'turtle/bin/setup/ios';\nimport { PLATFORMS } from 'turtle/constants';\n\nexport default async function setup(platform: string, sdkVersion?: string) {\n if (sdkVersion && !isSemver(sdkVersion)) {\n throw new Error('SDK version is not valid.');\n }\n\n if (platform === PLATFORMS.IOS) {\n return await setupIos(sdkVersion);\n } else if (platform === PLATFORMS.ANDROID) {\n return await setupAndroid(sdkVersion);\n } else {\n throw new Error('This should never happen :(');\n }\n}\n"]}
+89
View File
@@ -0,0 +1,89 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const fs_extra_1 = __importDefault(require("fs-extra"));
const tar_1 = __importDefault(require("tar"));
const downloader_1 = __importDefault(require("./downloader"));
const toolsDetector_1 = require("./toolsDetector");
const config_1 = __importDefault(require("../../../config"));
const logger_1 = __importDefault(require("../../../logger"));
const l = logger_1.default.child({ buildPhase: 'setting up environment' });
async function checkSystem(requiredTools) {
await toolsDetector_1.ensureToolsAreInstalled(requiredTools);
}
exports.checkSystem = checkSystem;
async function ensureShellAppIsPresent(sdkVersion, formatters, postDownloadAction) {
const workingdir = formatters.formatShellAppDirectory({ sdkVersion });
const shellAppMetadata = await _readShellAppTarballS3Uri(sdkVersion, formatters);
await removeDirectoryUnlessReady(workingdir, shellAppMetadata);
if (await fs_extra_1.default.pathExists(workingdir)) {
return;
}
l.info(`shell app for SDK ${sdkVersion} doesn't exist, downloading...`);
await _downloadShellApp(sdkVersion, workingdir, formatters);
if (postDownloadAction) {
await postDownloadAction(sdkVersion, workingdir);
}
await markDirectoryAsReady(workingdir, shellAppMetadata);
}
exports.ensureShellAppIsPresent = ensureShellAppIsPresent;
async function _downloadShellApp(sdkVersion, targetDirectory, formatters) {
const shellAppTarballS3Uri = await _readShellAppTarballS3Uri(sdkVersion, formatters);
const tarballDownloadTargetPath = formatArtifactDownloadPath(shellAppTarballS3Uri);
await fs_extra_1.default.ensureDir(config_1.default.directories.artifactsDir);
await downloader_1.default(shellAppTarballS3Uri, tarballDownloadTargetPath);
l.info('shell app has been downloaded');
await fs_extra_1.default.ensureDir(targetDirectory);
l.info('extracting shell app (this may take a while)...');
await tar_1.default.x({
file: tarballDownloadTargetPath,
C: targetDirectory,
});
l.info('shell app extracted');
}
function formatArtifactDownloadPath(uri) {
const { base } = path_1.default.parse(uri);
return path_1.default.join(config_1.default.directories.artifactsDir, base);
}
exports.formatArtifactDownloadPath = formatArtifactDownloadPath;
async function _readShellAppTarballS3Uri(sdkVersion, formatters) {
const sdkMajorVersion = xdl_1.ExponentTools.parseSdkMajorVersion(sdkVersion);
const filePath = formatters.formatShellAppTarballUriPath(sdkMajorVersion);
const data = await fs_extra_1.default.readFile(filePath, 'utf8');
return data.trim();
}
async function removeDirectoryUnlessReady(dir, metadata) {
const readyFilePath = path_1.default.join(dir, '.ready');
const readyFileExists = await fs_extra_1.default.pathExists(readyFilePath);
let shouldRemove = false;
if (readyFileExists) {
if (metadata !== undefined) {
const readyFileContents = (await fs_extra_1.default.readFile(readyFilePath, 'utf-8')).trim();
if (readyFileContents !== metadata) {
shouldRemove = true;
}
}
}
else {
shouldRemove = true;
}
if (shouldRemove) {
await fs_extra_1.default.remove(dir);
}
}
exports.removeDirectoryUnlessReady = removeDirectoryUnlessReady;
async function markDirectoryAsReady(dir, metadata) {
const readyFilePath = path_1.default.join(dir, '.ready');
if (metadata === undefined) {
await fs_extra_1.default.open(readyFilePath, 'w');
}
else {
await fs_extra_1.default.writeFile(readyFilePath, metadata);
}
}
exports.markDirectoryAsReady = markDirectoryAsReady;
//# sourceMappingURL=common.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../src/bin/setup/utils/common.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport { ExponentTools } from '@expo/xdl';\nimport fs from 'fs-extra';\nimport tar from 'tar';\n\nimport download from 'turtle/bin/setup/utils/downloader';\nimport { ensureToolsAreInstalled, IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';\nimport { IShellAppDirectoryConfig } from 'turtle/builders/utils/workingdir';\nimport config from 'turtle/config';\nimport logger from 'turtle/logger';\n\nconst l = logger.child({ buildPhase: 'setting up environment' });\n\ninterface IShellAppFormaters {\n formatShellAppDirectory: (config: IShellAppDirectoryConfig) => string;\n formatShellAppTarballUriPath: (sdkMajorVersion: string) => string;\n}\n\ntype PostDownloadAction = (sdkVersion: string, workingdir: string) => void;\n\nexport async function checkSystem(requiredTools: IToolDefinition[]) {\n await ensureToolsAreInstalled(requiredTools);\n}\n\nexport async function ensureShellAppIsPresent(\n sdkVersion: string,\n formatters: IShellAppFormaters,\n postDownloadAction?: PostDownloadAction,\n) {\n const workingdir = formatters.formatShellAppDirectory({ sdkVersion });\n const shellAppMetadata = await _readShellAppTarballS3Uri(sdkVersion, formatters);\n await removeDirectoryUnlessReady(workingdir, shellAppMetadata);\n if (await fs.pathExists(workingdir)) {\n return;\n }\n l.info(`shell app for SDK ${sdkVersion} doesn't exist, downloading...`);\n await _downloadShellApp(sdkVersion, workingdir, formatters);\n if (postDownloadAction) {\n await postDownloadAction(sdkVersion, workingdir);\n }\n await markDirectoryAsReady(workingdir, shellAppMetadata);\n}\n\nasync function _downloadShellApp(sdkVersion: string, targetDirectory: string, formatters: IShellAppFormaters) {\n const shellAppTarballS3Uri = await _readShellAppTarballS3Uri(sdkVersion, formatters);\n const tarballDownloadTargetPath = formatArtifactDownloadPath(shellAppTarballS3Uri);\n await fs.ensureDir(config.directories.artifactsDir);\n await download(shellAppTarballS3Uri, tarballDownloadTargetPath);\n l.info('shell app has been downloaded');\n await fs.ensureDir(targLine truncated
+49
View File
@@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const url_1 = require("url");
const progress_1 = __importDefault(require("progress"));
const request_1 = __importDefault(require("request"));
const request_progress_1 = __importDefault(require("request-progress"));
const S3_PROTOCOL = 's3:';
const PROGRESS_BAR_CONFIG = {
TEMPLATE: 'downloading [:bar] :percent :etas',
BAR: {
COMPLETE_CHAR: '=',
INCOMPLETE_CHAR: ' ',
WIDTH: 20,
},
};
async function download(url, destPath) {
const httpUrl = url.startsWith(S3_PROTOCOL) ? convertS3ToHttpsUrl(url) : url;
let bar;
return new Promise((res, rej) => {
request_progress_1.default(request_1.default(httpUrl))
.on('progress', (state) => {
if (!bar) {
bar = new progress_1.default(PROGRESS_BAR_CONFIG.TEMPLATE, {
complete: PROGRESS_BAR_CONFIG.BAR.COMPLETE_CHAR,
incomplete: PROGRESS_BAR_CONFIG.BAR.INCOMPLETE_CHAR,
width: PROGRESS_BAR_CONFIG.BAR.WIDTH,
total: state.size.total,
});
}
bar.tick(state.size.transferred - bar.curr);
})
.on('error', (err) => rej(err))
.on('end', () => res())
.pipe(fs_1.default.createWriteStream(destPath));
});
}
exports.default = download;
function convertS3ToHttpsUrl(s3UrlRaw) {
const { host: s3Bucket, pathname: s3Path, protocol } = new url_1.URL(s3UrlRaw);
if (protocol !== S3_PROTOCOL) {
throw new Error('Wrong S3 URL provided');
}
return `https://${s3Bucket}.s3.amazonaws.com${s3Path}`;
}
//# sourceMappingURL=downloader.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"downloader.js","sourceRoot":"","sources":["../../../../src/bin/setup/utils/downloader.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,6BAA0B;AAE1B,wDAAmC;AACnC,sDAA8B;AAC9B,wEAA+C;AAE/C,MAAM,WAAW,GAAG,KAAK,CAAC;AAC1B,MAAM,mBAAmB,GAAG;IAC1B,QAAQ,EAAE,mCAAmC;IAC7C,GAAG,EAAE;QACH,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,GAAG;QACpB,KAAK,EAAE,EAAE;KACV;CACF,CAAC;AAEa,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,QAAgB;IAClE,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7E,IAAI,GAAgB,CAAC;IAErB,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,0BAAe,CAAC,iBAAO,CAAC,OAAO,CAAC,CAAC;aAC9B,EAAE,CAAC,UAAU,EAAE,CAAC,KAAU,EAAE,EAAE;YAC3B,IAAI,CAAC,GAAG,EAAE;gBACR,GAAG,GAAG,IAAI,kBAAW,CAAC,mBAAmB,CAAC,QAAQ,EAAE;oBAClD,QAAQ,EAAE,mBAAmB,CAAC,GAAG,CAAC,aAAa;oBAC/C,UAAU,EAAE,mBAAmB,CAAC,GAAG,CAAC,eAAe;oBACnD,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK;oBACpC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;iBACxB,CAAC,CAAC;aACJ;YACD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAI,GAAW,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC,CAAC;aACD,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACrC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;aACtB,IAAI,CAAC,YAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC;AArBD,2BAqBC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,SAAG,CAAC,QAAQ,CAAC,CAAC;IACzE,IAAI,QAAQ,KAAK,WAAW,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;KAC1C;IACD,OAAO,WAAW,QAAQ,oBAAoB,MAAM,EAAE,CAAC;AACzD,CAAC","sourcesContent":["import fs from 'fs';\nimport { URL } from 'url';\n\nimport ProgressBar from 'progress';\nimport request from 'request';\nimport requestProgress from 'request-progress';\n\nconst S3_PROTOCOL = 's3:';\nconst PROGRESS_BAR_CONFIG = {\n TEMPLATE: 'downloading [:bar] :percent :etas',\n BAR: {\n COMPLETE_CHAR: '=',\n INCOMPLETE_CHAR: ' ',\n WIDTH: 20,\n },\n};\n\nexport default async function download(url: string, destPath: string) {\n const httpUrl = url.startsWith(S3_PROTOCOL) ? convertS3ToHttpsUrl(url) : url;\n let bar: ProgressBar;\n\n return new Promise((res, rej) => {\n requestProgress(request(httpUrl))\n .on('progress', (state: any) => {\n if (!bar) {\n bar = new ProgressBar(PROGRESS_BAR_CONFIG.TEMPLATE, {\n complete: PROGRESS_BAR_CONFIG.BAR.COMPLETE_CHAR,\n incomplete: PROGRESS_BAR_CONFIG.BAR.INCOMPLETE_CHAR,\n width: PROGRESS_BAR_CONFIG.BAR.WIDTH,\n total: state.size.total,\n });\n }\n bar.tick(state.size.transferred - (bar as any).curr);\n })\n .on('error', (err: Error) => rej(err))\n .on('end', () => res())\n .pipe(fs.createWriteStream(destPath));\n });\n}\n\nfunction convertS3ToHttpsUrl(s3UrlRaw: string) {\n const { host: s3Bucket, pathname: s3Path, protocol } = new URL(s3UrlRaw);\n if (protocol !== S3_PROTOCOL) {\n throw new Error('Wrong S3 URL provided');\n }\n return `https://${s3Bucket}.s3.amazonaws.com${s3Path}`;\n}\n"]}
+46
View File
@@ -0,0 +1,46 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = __importDefault(require("util"));
const which_1 = __importDefault(require("which"));
const logger_1 = __importDefault(require("../../../logger"));
const which = util_1.default.promisify(which_1.default);
const l = logger_1.default.child({ buildPhase: 'setting up environment' });
async function ensureToolsAreInstalled(tools) {
let isAnyToolMissing = false;
for (const { command, missingDescription, testFn, versionCheckFn } of tools) {
try {
if (testFn) {
if (!await testFn()) {
throw new Error('Required tool is not properly installed');
}
}
else {
await which(command);
}
}
catch (err) {
isAnyToolMissing = true;
if (!testFn) {
l.error({ err }, `${command} is missing in your $PATH`);
}
l.error({ err }, missingDescription);
}
if (versionCheckFn) {
try {
await versionCheckFn();
}
catch (err) {
isAnyToolMissing = true;
l.error({ err }, `wrong version of ${command} installed`);
}
}
}
if (isAnyToolMissing) {
throw new Error('Tools required to perform standalone app build are missing. Please install them.');
}
}
exports.ensureToolsAreInstalled = ensureToolsAreInstalled;
//# sourceMappingURL=toolsDetector.js.map
@@ -0,0 +1 @@
{"version":3,"file":"toolsDetector.js","sourceRoot":"","sources":["../../../../src/bin/setup/utils/toolsDetector.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AACxB,kDAA2B;AAE3B,6DAAmC;AAEnC,MAAM,KAAK,GAAG,cAAI,CAAC,SAAS,CAAC,eAAM,CAAC,CAAC;AACrC,MAAM,CAAC,GAAG,gBAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAS1D,KAAK,UAAU,uBAAuB,CAAC,KAAwB;IACpE,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,KAAK,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,KAAK,EAAE;QAC3E,IAAI;YACF,IAAI,MAAM,EAAE;gBACV,IAAI,CAAC,MAAM,MAAM,EAAE,EAAE;oBACnB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;iBAC5D;aACF;iBAAM;gBACL,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;aACtB;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,gBAAgB,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,MAAM,EAAE;gBACX,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,2BAA2B,CAAC,CAAC;aACzD;YACD,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;SACtC;QACD,IAAI,cAAc,EAAE;YAClB,IAAI;gBACF,MAAM,cAAc,EAAE,CAAC;aACxB;YAAC,OAAO,GAAG,EAAE;gBACZ,gBAAgB,GAAG,IAAI,CAAC;gBACxB,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,oBAAoB,OAAO,YAAY,CAAC,CAAC;aAC3D;SACF;KACF;IACD,IAAI,gBAAgB,EAAE;QACpB,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;KACrG;AACH,CAAC;AA9BD,0DA8BC","sourcesContent":["import util from 'util';\nimport _which from 'which';\n\nimport logger from 'turtle/logger';\n\nconst which = util.promisify(_which);\nconst l = logger.child({ buildPhase: 'setting up environment' });\n\nexport interface IToolDefinition {\n command: string;\n missingDescription: string;\n testFn?: () => Promise<boolean>;\n versionCheckFn?: () => void;\n}\n\nexport async function ensureToolsAreInstalled(tools: IToolDefinition[]) {\n let isAnyToolMissing = false;\n for (const { command, missingDescription, testFn, versionCheckFn } of tools) {\n try {\n if (testFn) {\n if (!await testFn()) {\n throw new Error('Required tool is not properly installed');\n }\n } else {\n await which(command);\n }\n } catch (err) {\n isAnyToolMissing = true;\n if (!testFn) {\n l.error({ err }, `${command} is missing in your $PATH`);\n }\n l.error({ err }, missingDescription);\n }\n if (versionCheckFn) {\n try {\n await versionCheckFn();\n } catch (err) {\n isAnyToolMissing = true;\n l.error({ err }, `wrong version of ${command} installed`);\n }\n }\n }\n if (isAnyToolMissing) {\n throw new Error('Tools required to perform standalone app build are missing. Please install them.');\n }\n}\n"]}
+123
View File
@@ -0,0 +1,123 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const url_1 = __importDefault(require("url"));
const xdl_1 = require("@expo/xdl");
const lodash_1 = __importDefault(require("lodash"));
const uuid_1 = __importDefault(require("uuid"));
const ErrorWithCommandHelp_1 = require("../commands/ErrorWithCommandHelp");
const ErrorWithProgramHelp_1 = require("../commands/ErrorWithProgramHelp");
const setup_1 = __importDefault(require("../setup/setup"));
const ProjectUtils = __importStar(require("./project"));
const UserUtils = __importStar(require("./user"));
const common_1 = require("../../builders/utils/common");
const logger_1 = __importDefault(require("../../logger"));
const validator_1 = require("../../validator");
function createBuilderAction({ program, command, prepareCredentials, builder, platform, os, }) {
return async (projectDirArg, cmd) => {
try {
const osList = [];
if (Array.isArray(os)) {
osList.push(...os);
}
else {
osList.push(os);
}
if (osList.length && !osList.includes(process.platform)) {
throw new Error('We don\'t support running standalone app builds for this platform on your operating system');
}
if (cmd.buildDir && cmd.output) {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('You can\'t provide both --build-dir and --output parameters, please choose one');
}
const userData = {
username: cmd.username || process.env.EXPO_USERNAME,
password: cmd.password || process.env.EXPO_PASSWORD,
};
if (userData.username || userData.password) {
if (userData.username && userData.password) {
await UserUtils.ensureUserLoggedIn(userData);
}
else {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('You must provide both Expo username and password');
}
}
else if (!cmd.publicUrl) {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('You must provide your Expo username and password unless you specify --public-url to your project manifest.');
}
if (cmd.publicUrl) {
const parsedPublicUrl = url_1.default.parse(cmd.publicUrl);
if (parsedPublicUrl.protocol !== 'https:') {
throw new ErrorWithCommandHelp_1.ErrorWithCommandHelp('--public-url is invalid - only HTTPS urls are supported');
}
}
const args = {
releaseChannel: cmd.releaseChannel || 'default',
buildType: cmd.type,
buildMode: cmd.mode,
username: userData.username || 'anonymous',
projectDir: ProjectUtils.resolveAbsoluteDir(projectDirArg),
publicUrl: cmd.publicUrl,
};
const appJSON = await ProjectUtils.loadAppJSON(projectDirArg, cmd.config);
const sdkVersion = lodash_1.default.get(appJSON, 'expo.sdkVersion');
await setup_1.default(platform, sdkVersion);
const credentials = await prepareCredentials(cmd);
const rawJob = {
...await buildJobObject(platform, appJSON, args, credentials),
...cmd.buildDir && { fakeUploadDir: ProjectUtils.resolveAbsoluteDir(cmd.buildDir) },
...cmd.output && { fakeUploadBuildPath: ProjectUtils.resolveAbsoluteDir(cmd.output) },
};
const job = await validator_1.sanitizeJob(rawJob);
await builder(job);
}
catch (err) {
logger_1.default.error({ err }, 'Failed to build standalone app');
if (err instanceof ErrorWithCommandHelp_1.ErrorWithCommandHelp) {
command.help();
}
else if (err instanceof ErrorWithProgramHelp_1.ErrorWithProgramHelp) {
program.help();
}
process.exit(1);
}
};
}
exports.createBuilderAction = createBuilderAction;
const buildJobObject = async (platform, appJSON, { releaseChannel, buildType, buildMode, username, publicUrl, projectDir }, credentials) => {
const experienceName = `@${lodash_1.default.get(appJSON, 'expo.owner', username)}/${lodash_1.default.get(appJSON, 'expo.slug')}`;
const job = {
config: {
...lodash_1.default.get(appJSON, `expo.${platform}.config`, {}),
buildType,
...(platform === 'android' ? { buildMode } : {}),
releaseChannel,
...(platform === 'ios' ? { bundleIdentifier: lodash_1.default.get(appJSON, 'expo.ios.bundleIdentifier') } : {}),
...(platform === 'android' ? { androidPackage: lodash_1.default.get(appJSON, 'expo.android.package') } : {}),
publicUrl,
},
id: uuid_1.default.v4(),
platform,
projectDir,
sdkVersion: lodash_1.default.get(appJSON, 'expo.sdkVersion'),
experienceName,
...(credentials && { credentials }),
};
const url = common_1.getExperienceUrl(job.experienceName, job.config.publicUrl);
const manifest = await xdl_1.ExponentTools.getManifestAsync(url, {
'Exponent-SDK-Version': lodash_1.default.get(appJSON, 'expo.sdkVersion'),
'Exponent-Platform': platform,
'Expo-Release-Channel': releaseChannel,
'Accept': 'application/expo+json,application/json',
});
return { ...job, manifest };
};
//# sourceMappingURL=builder.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/bin/utils/builder.ts"],"names":[],"mappings":"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","sourcesContent":["import _url from 'url';\n\nimport { ExponentTools } from '@expo/xdl';\nimport _ from 'lodash';\nimport uuid from 'uuid';\n\nimport { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';\nimport { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';\nimport setup from 'turtle/bin/setup/setup';\nimport * as ProjectUtils from 'turtle/bin/utils/project';\nimport * as UserUtils from 'turtle/bin/utils/user';\nimport { getExperienceUrl } from 'turtle/builders/utils/common';\nimport logger from 'turtle/logger';\nimport { sanitizeJob } from 'turtle/validator';\n\nexport function createBuilderAction({\n program,\n command,\n prepareCredentials,\n builder,\n platform,\n os,\n}: any) {\n return async (projectDirArg: string, cmd: any) => {\n try {\n const osList = [];\n if (Array.isArray(os)) {\n osList.push(...os);\n } else {\n osList.push(os);\n }\n if (osList.length && !osLiLine truncated
+35
View File
@@ -0,0 +1,35 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
async function loadAppJSON(projectDirArg, config) {
let appJSONPath;
if (config) {
appJSONPath = exports.resolveAbsoluteDir(config);
}
else {
const projectDir = exports.resolveAbsoluteDir(projectDirArg);
appJSONPath = path_1.default.join(projectDir, 'app.json');
}
const appJSONExists = await fs_extra_1.default.pathExists(appJSONPath);
if (!appJSONExists) {
throw new Error(`Couldn't find app.json.`);
}
else {
return require(appJSONPath);
}
}
exports.loadAppJSON = loadAppJSON;
exports.resolveAbsoluteDir = (dir) => {
if (dir && path_1.default.isAbsolute(dir)) {
return dir;
}
else {
const cwd = process.env.INIT_CWD || process.cwd();
return dir ? path_1.default.join(cwd, dir) : cwd;
}
};
//# sourceMappingURL=project.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/bin/utils/project.ts"],"names":[],"mappings":";;;;;AAAA,wDAA0B;AAC1B,gDAAwB;AAEjB,KAAK,UAAU,WAAW,CAAC,aAAqB,EAAE,MAAqB;IAC5E,IAAI,WAAW,CAAC;IAChB,IAAI,MAAM,EAAE;QACV,WAAW,GAAG,0BAAkB,CAAC,MAAM,CAAC,CAAC;KAC1C;SAAM;QACL,MAAM,UAAU,GAAG,0BAAkB,CAAC,aAAa,CAAC,CAAC;QACrD,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KACjD;IACD,MAAM,aAAa,GAAG,MAAM,kBAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IACvD,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;KAC5C;SAAM;QACL,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;KAC7B;AACH,CAAC;AAdD,kCAcC;AAEY,QAAA,kBAAkB,GAAG,CAAC,GAAW,EAAE,EAAE;IAChD,IAAI,GAAG,IAAI,cAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC/B,OAAO,GAAG,CAAC;KACZ;SAAM;QACL,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAClD,OAAO,GAAG,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;KACxC;AACH,CAAC,CAAC","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\n\nexport async function loadAppJSON(projectDirArg: string, config: string | null) {\n let appJSONPath;\n if (config) {\n appJSONPath = resolveAbsoluteDir(config);\n } else {\n const projectDir = resolveAbsoluteDir(projectDirArg);\n appJSONPath = path.join(projectDir, 'app.json');\n }\n const appJSONExists = await fs.pathExists(appJSONPath);\n if (!appJSONExists) {\n throw new Error(`Couldn't find app.json.`);\n } else {\n return require(appJSONPath);\n }\n}\n\nexport const resolveAbsoluteDir = (dir: string) => {\n if (dir && path.isAbsolute(dir)) {\n return dir;\n } else {\n const cwd = process.env.INIT_CWD || process.cwd();\n return dir ? path.join(cwd, dir) : cwd;\n }\n};\n"]}
+23
View File
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const xdl_1 = require("@expo/xdl");
const ErrorWithProgramHelp_1 = require("../commands/ErrorWithProgramHelp");
async function ensureUserLoggedIn(userData) {
const currentUser = await xdl_1.UserManager.getCurrentUserAsync();
if (currentUser) {
return currentUser;
}
else if (!userData.username || !userData.password) {
throw new ErrorWithProgramHelp_1.ErrorWithProgramHelp('Please provide username and password');
}
else {
try {
return await xdl_1.UserManager.loginAsync('user-pass', userData);
}
catch (err) {
throw new Error('Failed to log in with provided username and password');
}
}
}
exports.ensureUserLoggedIn = ensureUserLoggedIn;
//# sourceMappingURL=user.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../../src/bin/utils/user.ts"],"names":[],"mappings":";;AAAA,mCAAwC;AAExC,2EAAgF;AAOzE,KAAK,UAAU,kBAAkB,CAAC,QAAmB;IAC1D,MAAM,WAAW,GAAG,MAAM,iBAAW,CAAC,mBAAmB,EAAE,CAAC;IAC5D,IAAI,WAAW,EAAE;QACf,OAAO,WAAW,CAAC;KACpB;SAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACnD,MAAM,IAAI,2CAAoB,CAAC,sCAAsC,CAAC,CAAC;KACxE;SAAM;QACL,IAAI;YACF,OAAO,MAAM,iBAAW,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;SAC5D;QAAC,OAAO,GAAG,EAAE;YACZ,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;SACzE;KACF;AACH,CAAC;AAbD,gDAaC","sourcesContent":["import { UserManager } from '@expo/xdl';\n\nimport { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';\n\ninterface IUserData {\n username?: string;\n password?: string;\n}\n\nexport async function ensureUserLoggedIn(userData: IUserData) {\n const currentUser = await UserManager.getCurrentUserAsync();\n if (currentUser) {\n return currentUser;\n } else if (!userData.username || !userData.password) {\n throw new ErrorWithProgramHelp('Please provide username and password');\n } else {\n try {\n return await UserManager.loginAsync('user-pass', userData);\n } catch (err) {\n throw new Error('Failed to log in with provided username and password');\n }\n }\n}\n"]}
+17
View File
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class BuildError extends Error {
constructor(reason, message) {
super(message);
this.name = 'BuildError';
this.reason = reason;
}
}
var BuildErrorReason;
(function (BuildErrorReason) {
BuildErrorReason["SESSION_EXPIRED"] = "session-expired";
BuildErrorReason["PROVISIONING_PROFILE_MISSING"] = "provisioning-profile-missing";
})(BuildErrorReason || (BuildErrorReason = {}));
exports.BuildErrorReason = BuildErrorReason;
exports.default = BuildError;
//# sourceMappingURL=BuildError.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"BuildError.js","sourceRoot":"","sources":["../../src/builders/BuildError.ts"],"names":[],"mappings":";;AAAA,MAAM,UAAW,SAAQ,KAAK;IAG5B,YAAY,MAAwB,EAAE,OAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,IAAK,gBAGJ;AAHD,WAAK,gBAAgB;IACnB,uDAAmC,CAAA;IACnC,iFAA6D,CAAA;AAC/D,CAAC,EAHI,gBAAgB,KAAhB,gBAAgB,QAGpB;AAGQ,4CAAgB;AADzB,kBAAe,UAAU,CAAC","sourcesContent":["class BuildError extends Error {\n public reason: BuildErrorReason;\n\n constructor(reason: BuildErrorReason, message: string) {\n super(message);\n this.name = 'BuildError';\n this.reason = reason;\n }\n}\n\nenum BuildErrorReason {\n SESSION_EXPIRED = 'session-expired',\n PROVISIONING_PROFILE_MISSING = 'provisioning-profile-missing',\n}\n\nexport default BuildError;\nexport { BuildErrorReason };\n"]}
+108
View File
@@ -0,0 +1,108 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const fs_extra_1 = __importDefault(require("fs-extra"));
const lodash_1 = __importDefault(require("lodash"));
const semver_1 = __importDefault(require("semver"));
const constants_1 = require("../constants");
const v4_1 = __importDefault(require("uuid/v4"));
const credentials_1 = __importDefault(require("./utils/android/credentials"));
const workingdir_1 = require("./utils/android/workingdir");
const commonUtils = __importStar(require("./utils/common"));
const imageHelpers = __importStar(require("./utils/image"));
const unimodules_1 = require("./utils/unimodules");
const uploader_1 = require("./utils/uploader");
const version_1 = require("./utils/version");
const config_1 = __importDefault(require("../config"));
const logger_1 = __importDefault(require("../logger"));
async function buildAndroid(jobData) {
await version_1.ensureCanBuildSdkVersion(jobData);
const credentials = await credentials_1.default(jobData);
const outputFilePath = await runShellAppBuilder(jobData, credentials);
const randomHex = v4_1.default().replace(/-/g, '');
const s3FileExtension = jobData.config.buildType === constants_1.ANDROID_BUILD_TYPES.APP_BUNDLE ? 'aab' : 'apk';
const s3Filename = `${jobData.experienceName}-${randomHex}-signed.${s3FileExtension}`;
const s3FileKey = `android/${s3Filename}`;
const fakeUploadFilename = s3Filename.replace('/', '__');
const artifactUrl = await uploader_1.uploadBuildToS3({
uploadPath: outputFilePath,
s3FileKey,
...config_1.default.builder.fakeUpload && {
fakeUploadBuildPath: jobData.fakeUploadBuildPath
? jobData.fakeUploadBuildPath
: path_1.default.join(jobData.fakeUploadDir || config_1.default.directories.fakeUploadDir, fakeUploadFilename),
},
});
return { artifactUrl };
}
exports.default = buildAndroid;
async function runShellAppBuilder(jobData, credentials) {
const { temporaryFilesRoot } = config_1.default.directories;
await fs_extra_1.default.ensureDir(temporaryFilesRoot);
const tempShellAppConfigPath = path_1.default.join(temporaryFilesRoot, `app-config-${jobData.id}.json`);
const tempKeystorePath = path_1.default.join(temporaryFilesRoot, `keystore-${jobData.id}.jks`);
const configJSON = JSON.stringify(jobData.config);
await fs_extra_1.default.writeFile(tempShellAppConfigPath, configJSON, { mode: 0o644 });
await fs_extra_1.default.writeFile(tempKeystorePath, Buffer.from(credentials.keystore, 'base64'), {
mode: 0o600,
});
logger_1.default.info({ buildPhase: 'starting builder' }, 'Starting build process');
logger_1.default.info({ buildPhase: 'icons setup' }, 'ImageUtils: setting image functions to alternative sharp implementations');
xdl_1.ImageUtils.setResizeImageFunction(imageHelpers.resizeIconWithSharpAsync);
xdl_1.ImageUtils.setGetImageDimensionsFunction(imageHelpers.getImageDimensionsWithSharpAsync);
const fileExtension = jobData.config.buildType === constants_1.ANDROID_BUILD_TYPES.APP_BUNDLE ? 'aab' : 'apk';
const outputFilePath = path_1.default.join(temporaryFilesRoot, `shell-signed-${jobData.id}.${fileExtension}`);
const { config: jobConfig, manifest, sdkVersion: sdkVersionFromJob } = jobData;
const sdkVersion = lodash_1.default.get(manifest, 'sdkVersion', sdkVersionFromJob);
const workingDir = workingdir_1.formatShellAppDirectory({ sdkVersion });
// (2019-07-31) We are explicitly choosing to disable this option until we have more
// infrastructure/tooling built around optional modules and OTA updates, as right now it's
// very easy for developers to break apps in production with optional modules.
//
// to enable full resolver switch resolveExplicitOptIn to resolveNativeModules
logger_1.default.info({ buildPhase: 'resolve native modules' }, 'Resolving universal modules dependencies');
const enabledModules = semver_1.default.satisfies(sdkVersion, '>= 33.0.0')
? await unimodules_1.resolveExplicitOptIn(workingDir, lodash_1.default.get(manifest, 'dependencies'))
: null;
try {
await xdl_1.AndroidShellApp.createAndroidShellAppAsync({
url: commonUtils.getExperienceUrl(jobData.experienceName, jobData.config.publicUrl),
sdkVersion,
keystore: tempKeystorePath,
manifest,
alias: credentials.keystoreAlias,
keystorePassword: credentials.keystorePassword,
keyPassword: credentials.keyPassword,
privateConfigFile: tempShellAppConfigPath,
releaseChannel: jobConfig.releaseChannel,
workingDir,
outputFile: outputFilePath,
modules: enabledModules,
buildType: jobData.config.buildType,
buildMode: jobData.config.buildMode,
});
}
catch (err) {
commonUtils.logErrorOnce(err);
throw err;
}
finally {
if (!config_1.default.builder.skipCleanup) {
await fs_extra_1.default.unlink(tempShellAppConfigPath);
await fs_extra_1.default.unlink(tempKeystorePath);
}
}
return outputFilePath;
}
//# sourceMappingURL=android.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"android.js","sourceRoot":"","sources":["../../src/builders/android.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport { AndroidShellApp, ImageUtils } from '@expo/xdl';\nimport fs from 'fs-extra';\nimport _ from 'lodash';\nimport semver from 'semver';\nimport { ANDROID_BUILD_TYPES } from 'turtle/constants';\nimport uuidv4 from 'uuid/v4';\n\nimport getOrCreateCredentials from 'turtle/builders/utils/android/credentials';\nimport { formatShellAppDirectory } from 'turtle/builders/utils/android/workingdir';\nimport * as commonUtils from 'turtle/builders/utils/common';\nimport * as imageHelpers from 'turtle/builders/utils/image';\nimport { resolveExplicitOptIn } from 'turtle/builders/utils/unimodules';\nimport { uploadBuildToS3 } from 'turtle/builders/utils/uploader';\nimport { ensureCanBuildSdkVersion } from 'turtle/builders/utils/version';\nimport config from 'turtle/config';\nimport { IAndroidCredentials, IJob, IJobResult } from 'turtle/job';\nimport logger from 'turtle/logger';\n\nexport default async function buildAndroid(jobData: IJob): Promise<IJobResult> {\n await ensureCanBuildSdkVersion(jobData);\n const credentials = await getOrCreateCredentials(jobData);\n const outputFilePath = await runShellAppBuilder(jobData, credentials);\n\n const randomHex = uuidv4().replace(/-/g, '');\n const s3FileExtension = jobData.config.buildType === ANDROID_BUILD_TYPES.APP_BUNDLE ? 'aab' : 'apk';\n const s3Filename = `${jobLine truncated
+12
View File
@@ -0,0 +1,12 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const android_1 = __importDefault(require("./android"));
const ios_1 = __importDefault(require("./ios"));
exports.default = {
ios: ios_1.default,
android: android_1.default,
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":";;;;;AAAA,wDAAqC;AACrC,gDAA6B;AAE7B,kBAAe;IACb,GAAG,EAAE,aAAQ;IACb,OAAO,EAAE,iBAAY;CACtB,CAAC","sourcesContent":["import buildAndroid from './android';\nimport buildIOS from './ios';\n\nexport default {\n ios: buildIOS,\n android: buildAndroid,\n};\n"]}
+64
View File
@@ -0,0 +1,64 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const xdl_1 = require("@expo/xdl");
const lodash_1 = __importDefault(require("lodash"));
const common_1 = require("../utils/common");
const fileUtils = __importStar(require("../utils/file"));
const keychain = __importStar(require("../utils/ios/keychain"));
const shellAppBuilder_1 = __importDefault(require("../utils/ios/shellAppBuilder"));
const index_1 = __importDefault(require("../../logger/index"));
async function buildArchive(ctx, job) {
let keychainInfo;
try {
keychainInfo = await keychain.create(ctx);
const { credentials } = job;
const { certP12, certPassword } = credentials;
await keychain.importCert(ctx, { keychainPath: keychainInfo.path, certP12, certPassword });
const manifest = await shellAppBuilder_1.default(ctx, job);
await buildAndSignIPA(ctx, job, keychainInfo.path, manifest);
}
catch (err) {
common_1.logErrorOnce(err);
throw err;
}
finally {
if (keychainInfo) {
await keychain.remove(ctx, keychainInfo.path);
}
}
}
exports.default = buildArchive;
async function buildAndSignIPA(ctx, job, keychainPath, manifest) {
const l = index_1.default.child({ buildPhase: 'building and signing IPA' });
l.info('building and signing IPA');
const { credentials: { provisioningProfile, certPassword, teamId }, config: { bundleIdentifier: bundleIdentifierFromConfig }, } = job;
const bundleIdentifierFromManifest = lodash_1.default.get(manifest, 'ios.bundleIdentifier');
const bundleIdentifier = bundleIdentifierFromConfig || bundleIdentifierFromManifest;
const { provisioningProfilePath } = ctx;
await fileUtils.writeBase64ToBinaryFile(provisioningProfilePath, provisioningProfile);
l.info('saved provisioning profile to temporary path');
const ipaBuilder = xdl_1.IosIPABuilder({
keychainPath,
provisioningProfilePath,
appUUID: ctx.appUUID,
certPath: ctx.tempCertPath,
certPassword,
teamID: teamId,
bundleIdentifier,
workspacePath: ctx.workspacePath,
manifest,
});
await ipaBuilder.build();
l.info(`done building and signing IPA`);
}
//# sourceMappingURL=archive.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../../src/builders/ios/archive.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mCAA8D;AAC9D,oDAAuB;AAGvB,4CAA4D;AAC5D,yDAAwD;AACxD,gEAA+D;AAC/D,mFAA2E;AAE3E,+DAAyC;AAE1B,KAAK,UAAU,YAAY,CAAC,GAAa,EAAE,GAAS;IACjE,IAAI,YAAY,CAAC;IACjB,IAAI;QACF,YAAY,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;QAC5B,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,WAAwD,CAAC;QAC3F,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QAC3F,MAAM,QAAQ,GAAG,MAAM,yBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KAC9D;IAAC,OAAO,GAAG,EAAE;QACZ,qBAAY,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,GAAG,CAAC;KACX;YAAS;QACR,IAAI,YAAY,EAAE;YAChB,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;SAC/C;KACF;AACH,CAAC;AAjBD,+BAiBC;AAED,KAAK,UAAU,eAAe,CAAC,GAAa,EAAE,GAAS,EAAE,YAAoB,EAAE,QAAa;IAC1F,MAAM,CAAC,GAAG,eAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,0BAA0B,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAEnC,MAAM,EACJ,WAAW,EAAE,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,EAAE,EAC1D,MAAM,EAAE,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,GACzD,GAAG,GAAG,CAAC;IAER,MAAM,4BAA4B,GAAG,gBAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IAC7E,MAAM,gBAAgB,GAAG,0BAA0B,IAAI,4BAA4B,CAAC;IAEpF,MAAM,EAAE,uBAAuB,EAAE,GAAG,GAAG,CAAC;IACxC,MAAM,SAAS,CAAC,uBAAuB,CAAC,uBAAuB,EAAE,mBAA6B,CAAC,CAAC;IAChG,CAAC,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,mBAAgB,CAAC;QAClC,YAAY;QACZ,uBAAuB;QACvB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,YAAY;QAC1B,YAAY;QACZ,MAAM,EAAE,MAAM;QACd,gBAAgB;QAChB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,QAAQ;KACT,CAAC,CAAC;IACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAEzB,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["import { IosIPABuilder as createIPABuilder } from '@expo/xdl';\nimport _ from 'lodash';\n\nimport { IContext } from 'turtle/builders/ios/context';\nimport { logErrorOnce } from 'turtle/builders/utils/common';\nimport * as fileUtils from 'turtle/builders/utils/file';\nimport * as keychain from 'turtle/builders/utils/ios/keychain';\nimport runShellAppBuilder from 'turtle/builders/utils/ios/shellAppBuilder';\nimport { IJob } from 'turtle/job';\nimport logger from 'turtle/logger/index';\n\nexport default async function buildArchive(ctx: IContext, job: IJob) {\n let keychainInfo;\n try {\n keychainInfo = await keychain.create(ctx);\n const { credentials } = job;\n const { certP12, certPassword } = credentials as { certP12: string; certPassword: string };\n await keychain.importCert(ctx, { keychainPath: keychainInfo.path, certP12, certPassword });\n const manifest = await runShellAppBuilder(ctx, job);\n await buildAndSignIPA(ctx, job, keychainInfo.path, manifest);\n } catch (err) {\n logErrorOnce(err);\n throw err;\n } finally {\n if (keychainInfo) {\n await keychain.remove(ctx, keychainInfo.path);\n }\n }\n}\n\nasync function buildAndSignIPA(ctx: IContext, job: IJob, keychainPath: string, manifest: any) {\n const l = logger.child({ buildPhase: 'building and signing IPA' });\n l.info('building and signing IPA');\n\n const {\n credentials: { provisioningProfile, certPassword, teamId },\n config: { bundleIdentifier: bundleIdentifierFromConfig },\n } = job;\n\n const bundleIdentifierFromManifest = _.get(manifest, 'ios.bundleIdentifier');\n const bundleIdentifier = bundleIdentifierFromConfig || bundleIdentifierFromManifest;\n\n const { provisioningProfilePath } = ctx;\n await fileUtils.writeBase64ToBinaryFile(provisioningProfilePath, provisioningProfile as string);\n l.info('saved provisioning profile to temporary path');\n\n const ipaBuilder = createIPABuilder({\n keychainPath,\n provisioningProfilePath,\n appUUID: ctx.appUUID,\n certPath: ctx.tempCertPath,\n certPassword,\n teamID: teamId,\n bundleIdentifier,\n workspacePath: ctx.workspacePath,\n manifest,\n });\n await ipaBuilder.build();\n\n l.info(`done building and signing IPA`);\n}\n"]}
+79
View File
@@ -0,0 +1,79 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(require("path"));
const xdl_1 = require("@expo/xdl");
const uuid_1 = require("uuid");
const workingdir_1 = require("../utils/ios/workingdir");
const config_1 = __importDefault(require("../../config"));
const index_1 = require("../../constants/index");
const { EXPOKIT_APP, EXPONENT_APP } = xdl_1.IosShellApp;
function createBuilderContext(job) {
const { join } = path;
const appUUID = uuid_1.v4();
const { manifest: { sdkVersion: sdkVersionFromManifest = null, } = {}, sdkVersion: sdkVersionFromJob, config: { buildType }, } = job;
const sdkVersion = sdkVersionFromJob || sdkVersionFromManifest;
const workingDir = workingdir_1.formatShellAppDirectory({ sdkVersion, buildType: buildType });
const majorSdkVersion = xdl_1.ExponentTools.parseSdkMajorVersion(sdkVersion);
const context = {
appDir: join(config_1.default.directories.temporaryFilesRoot, appUUID),
appUUID,
workingDir,
};
context.buildDir = join(context.appDir, 'build');
context.provisioningProfileDir = join(context.appDir, 'provisioning');
context.provisioningProfilePath = join(context.provisioningProfileDir, `${appUUID}.mobileprovision`);
context.tempCertPath = join(context.appDir, 'cert.p12');
context.baseArchiveDir = join(context.appDir, 'archive');
if (buildType === index_1.IOS_BUILD_TYPES.CLIENT) {
context.applicationFilesSrc = join(workingDir, 'expo-client-build', '**', '*');
}
else {
context.applicationFilesSrc = join(workingDir, 'shellAppBase-builds', buildType, '**', '*');
}
if (buildType === index_1.IOS_BUILD_TYPES.ARCHIVE) {
context.outputPath = join(context.appDir, 'archive.xcarchive');
context.uploadPath = join(context.buildDir, 'archive.ipa');
context.archiveDir = join(context.baseArchiveDir, 'Release', `${EXPOKIT_APP}.xcarchive`, 'Products', 'Applications', `${EXPOKIT_APP}.app`);
if (majorSdkVersion >= 33) {
context.workspacePath = path.join(workingDir, 'shellAppWorkspaces', 'default', 'ios', `${EXPOKIT_APP}.xcworkspace`);
}
else {
context.workspacePath = path.join(workingDir, 'shellAppWorkspaces', 'ios', 'default', `${EXPOKIT_APP}.xcworkspace`);
}
}
else if (buildType === index_1.IOS_BUILD_TYPES.CLIENT) {
context.outputPath = join(context.appDir, 'archive.xcarchive');
context.uploadPath = join(context.buildDir, 'archive.ipa');
context.archiveDir = join(context.baseArchiveDir, `${EXPONENT_APP}.xcarchive`, 'Products', 'Applications', `${EXPONENT_APP}.app`);
context.workspacePath = path.join(workingDir, 'ios', `${EXPONENT_APP}.xcworkspace`);
}
else if (buildType === index_1.IOS_BUILD_TYPES.SIMULATOR) {
context.outputPath = join(context.appDir, 'archive.tar.gz');
context.uploadPath = join(context.appDir, 'archive.tar.gz');
context.archiveDir = join(context.baseArchiveDir, 'Release', `${EXPOKIT_APP}.app`);
}
const s3FileExtension = buildType === index_1.IOS_BUILD_TYPES.SIMULATOR ? 'tar.gz' : 'ipa';
const s3Filename = `${job.experienceName}-${appUUID}-${buildType}.${s3FileExtension}`;
if (config_1.default.builder.fakeUpload) {
const fakeUploadFilename = s3Filename.replace('/', '__');
context.fakeUploadBuildPath = job.fakeUploadBuildPath
? job.fakeUploadBuildPath
: join(job.fakeUploadDir || config_1.default.directories.fakeUploadDir, fakeUploadFilename);
}
else {
context.s3FileKey = join(index_1.PLATFORMS.IOS, s3Filename);
}
return context;
}
exports.createBuilderContext = createBuilderContext;
//# sourceMappingURL=context.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/builders/ios/context.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA6B;AAE7B,mCAAuD;AACvD,+BAAoC;AAEpC,wDAA+E;AAC/E,0DAAmC;AACnC,iDAAoE;AAqBpE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,iBAAW,CAAC;AAElD,SAAgB,oBAAoB,CAAC,GAAS;IAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACtB,MAAM,OAAO,GAAG,SAAM,EAAE,CAAC;IACzB,MAAM,EACJ,QAAQ,EAAE,EACR,UAAU,EAAE,sBAAsB,GAAG,IAAI,GAC1C,GAAG,EAAE,EACN,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,EAAE,SAAS,EAAE,GACtB,GAAG,GAAG,CAAC;IAER,MAAM,UAAU,GAAG,iBAAiB,IAAI,sBAAsB,CAAC;IAC/D,MAAM,UAAU,GAAG,oCAAuB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,SAAU,EAAE,CAAC,CAAC;IAClF,MAAM,eAAe,GAAG,mBAAa,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAQ;QACnB,MAAM,EAAE,IAAI,CAAC,gBAAM,CAAC,WAAW,CAAC,kBAAkB,EAAE,OAAO,CAAC;QAC5D,OAAO;QACP,UAAU;KACX,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACtE,OAAO,CAAC,uBAAuB,GAAG,IAAI,CACpC,OAAO,CAAC,sBAAsB,EAC9B,GAAG,OAAO,kBAAkB,CAC7B,CAAC;IACF,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxD,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEzD,IAAI,SAAS,KAAK,uBAAe,CAAC,MAAM,EAAE;QACxC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAChC,UAAU,EACV,mBAAmB,EACnB,IAAI,EACJ,GAAG,CACJ,CAAC;KACH;SAAM;QACL,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAChC,UAAU,EACV,qBAAqB,EACrB,SAAmB,EACnB,IAAI,EACJ,GAAG,CACJ,CAAC;KACH;IAED,IAAI,SAAS,KAAK,uBAAe,CAAC,OAAO,EAAE;QACzC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;QAC/D,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC3D,OAAO,CAAC,UAAU,GAAG,IAAI,CACvB,OAAO,CAAC,cAAc,EACtB,SAAS,EACT,GAAG,WAAW,YAAY,EAC1B,UAAU,EACV,cAAc,EACd,GAAG,WAAW,MAAM,CACrB,CAAC;QACF,IAAI,eAAe,IAAI,EAAE,EAAE;YACzB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAC/B,UAAU,EACV,oBAAoB,EACpB,SAAS,EACT,KAAK,EACL,GAAG,WAAW,cAAc,CAC7B,CAAC;SACH;aAAM;YACL,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAC/B,UAAU,EACV,oBAAoB,EACpB,KAAK,EACL,SAAS,EACT,GAAG,WAAW,cAAc,CAC7B,CAAC;SACH;KAEF;SAAM,IAAI,SAAS,KAAK,uBAAe,CAAC,MAAM,EAAE;QAC/C,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;QAC/D,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC3D,OAAO,CAAC,UAAU,GAAG,IAAI,CACvB,OAAO,CAAC,cAAc,EACtB,GAAG,YAAY,YAAY,EAC3B,UAAU,EACV,cAAc,EACd,GAAG,YAAY,MAAM,CACtB,CAAC;QACF,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAC/B,UAAU,EACV,KAAK,EACL,GAAG,YAAY,cAAc,CAC9B,CAAC;KACH;SAAM,IAAI,SAAS,KAAK,uBAAe,CAAC,SAAS,EAAE;QAClD,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC5D,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC5D,OAAO,CAAC,UAAU,GAAG,IAAI,CACvB,OAAO,CAAC,cAAc,EACtB,SAAS,EACT,GAAG,WAAW,MAAM,CACrB,CAAC;KACH;IAED,MAAM,eAAe,GAAG,SAAS,KAAK,uBAAe,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IACnF,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,cAAc,IAAI,OAAO,IAAI,SAAS,IAAI,eAAe,EAAE,CAAC;IACtF,IAAI,gBAAM,CAAC,OAAO,CAAC,UAAU,EAAE;QAC7B,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,CAAC,mBAAmB,GAAG,GAAG,CAAC,mBAAmB;YACnD,CAAC,CAAC,GAAG,CAAC,mBAAmB;YACzB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,gBAAM,CAAC,WAAW,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;KACrF;SAAM;QACL,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,iBAAS,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;KACrD;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAhHD,oDAgHC","sourcesContent":["import * as path from 'path';\n\nimport { ExponentTools, IosShellApp } from '@expo/xdl';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { formatShellAppDirectory } from 'turtle/builders/utils/ios/workingdir';\nimport config from 'turtle/config';\nimport { IOS_BUILD_TYPES, PLATFORMS } from 'turtle/constants/index';\nimport { IJob } from 'turtle/job';\n\nexport interface IContext {\n appDir: string;\n appUUID: string;\n archiveDir: string;\n baseArchiveDir: string;\n buildDir: string;\n fakeUploadBuildPath?: string;\n outputPath: string;\n provisioningProfilePath: string;\n provisioningProfileDir: string;\n s3FileKey?: string;\n tempCertPath: string;\n uploadPath: string;\n workingDir: string;\n workspacePath: string;\n applicationFilesSrc: string;\n}\n\nconst { EXPOKIT_APP, EXPONENT_APP } = IosShellApp;\n\nexport function createBuilderContext(job: IJob): IContext {\n const { join } = path;\n const appUUID = uuidv4();\n const {\n manifest: {\n sdkVersion: sdkVersionFromManifest = null,\n } = {},\n sdkVersion: sdkVersionFromJob,\n config: { buildType },\n } = job;\n\n const sdkVersion = sdkVersionFromJob || sdkVersionFromManifest;\n const workingDir = formatShellAppDirectory({ sdkVersion, buildType: buildType! });\n const majorSdkVersion = ExponentTools.parseSdkMajorVersion(sdkVersion);\n\n const context: any = {\n appDir: join(config.directories.temporaryFilesRoot, appUUID),\n appUUID,\n workingDir,\n };\n context.buildDir = join(context.appDir, 'build');\n context.provisioningProfileDir = join(context.appDir, 'provisioning');\n context.provisioningProfilePath = join(\n context.prLine truncated
+62
View File
@@ -0,0 +1,62 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const pick_1 = __importDefault(require("lodash/pick"));
const archive_1 = __importDefault(require("./archive"));
const context_1 = require("./context");
const simulator_1 = __importDefault(require("./simulator"));
const common_1 = require("../utils/common");
const adhocBuild_1 = __importDefault(require("../utils/ios/adhocBuild"));
const uploader_1 = require("../utils/uploader");
const version_1 = require("../utils/version");
const config_1 = __importDefault(require("../../config"));
const constants_1 = require("../../constants");
async function iosBuilder(job) {
if (job.config.buildType !== constants_1.IOS_BUILD_TYPES.CLIENT) {
await version_1.ensureCanBuildSdkVersion(job);
}
const ctx = context_1.createBuilderContext(job);
try {
await initBuilder(ctx);
const { buildType } = job.config;
if (buildType === constants_1.IOS_BUILD_TYPES.CLIENT) {
await adhocBuild_1.default(job);
}
if ([constants_1.IOS_BUILD_TYPES.ARCHIVE, constants_1.IOS_BUILD_TYPES.CLIENT].includes(buildType)) {
await archive_1.default(ctx, job);
}
else if (buildType === constants_1.IOS_BUILD_TYPES.SIMULATOR) {
await simulator_1.default(ctx, job);
}
else {
throw new Error(`Unsupported iOS build type: ${buildType}`);
}
const artifactUrl = await uploader_1.uploadBuildToS3(ctx);
return { artifactUrl };
}
catch (err) {
common_1.logErrorOnce(err);
throw err;
}
finally {
await cleanup(ctx);
}
}
exports.default = iosBuilder;
async function initBuilder(ctx) {
for (const dir of getTemporaryDirs(ctx)) {
await fs_extra_1.default.ensureDir(dir);
await fs_extra_1.default.chmod(dir, 0o755);
}
}
async function cleanup(ctx) {
if (config_1.default.builder.skipCleanup) {
return;
}
await Promise.all(getTemporaryDirs(ctx).map((dir) => fs_extra_1.default.remove(dir)));
}
const getTemporaryDirs = (ctx) => Object.values(pick_1.default(ctx, ['appDir', 'provisioningProfileDir']));
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/builders/ios/index.ts"],"names":[],"mappings":";;;;;AAAA,wDAA0B;AAC1B,uDAA+B;AAE/B,wDAAuD;AACvD,uCAA6E;AAC7E,4DAA2D;AAC3D,4CAA4D;AAC5D,yEAAgF;AAChF,gDAAiE;AACjE,8CAAyE;AACzE,0DAAmC;AACnC,+CAAmD;AAGpC,KAAK,UAAU,UAAU,CAAC,GAAS;IAChD,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,2BAAe,CAAC,MAAM,EAAE;QACnD,MAAM,kCAAwB,CAAC,GAAG,CAAC,CAAC;KACrC;IAED,MAAM,GAAG,GAAG,8BAAoB,CAAC,GAAG,CAAC,CAAC;IAEtC,IAAI;QACF,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QAEvB,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAEjC,IAAI,SAAS,KAAK,2BAAe,CAAC,MAAM,EAAE;YACxC,MAAM,oBAA4B,CAAC,GAAG,CAAC,CAAC;SACzC;QAED,IAAI,CAAC,2BAAe,CAAC,OAAO,EAAE,2BAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAU,CAAC,EAAE;YAC1E,MAAM,iBAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SAC9B;aAAM,IAAI,SAAS,KAAK,2BAAe,CAAC,SAAS,EAAE;YAClD,MAAM,mBAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SAChC;aAAM;YACL,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAC;SAC7D;QAED,MAAM,WAAW,GAAG,MAAM,0BAAe,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,EAAE,WAAW,EAAE,CAAC;KACxB;IAAC,OAAO,GAAG,EAAE;QACZ,qBAAY,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,GAAG,CAAC;KACX;YAAS;QACR,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;KACpB;AACH,CAAC;AAhCD,6BAgCC;AAED,KAAK,UAAU,WAAW,CAAC,GAAa;IACtC,KAAK,MAAM,GAAG,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE;QACvC,MAAM,kBAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,MAAM,kBAAE,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;KAC5B;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAa;IAClC,IAAI,gBAAM,CAAC,OAAO,CAAC,WAAW,EAAE;QAC9B,OAAO;KACR;IACD,MAAM,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,kBAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,GAAa,EAAE,EAAE,CACzC,MAAM,CAAC,MAAM,CAAC,cAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC,CAAa,CAAC","sourcesContent":["import fs from 'fs-extra';\nimport pick from 'lodash/pick';\n\nimport buildArchive from 'turtle/builders/ios/archive';\nimport { createBuilderContext, IContext } from 'turtle/builders/ios/context';\nimport buildSimulator from 'turtle/builders/ios/simulator';\nimport { logErrorOnce } from 'turtle/builders/utils/common';\nimport prepareAdHocBuildCredentials from 'turtle/builders/utils/ios/adhocBuild';\nimport { uploadBuildToS3 } from 'turtle/builders/utils/uploader';\nimport { ensureCanBuildSdkVersion } from 'turtle/builders/utils/version';\nimport config from 'turtle/config';\nimport { IOS_BUILD_TYPES } from 'turtle/constants';\nimport { IJob, IJobResult } from 'turtle/job';\n\nexport default async function iosBuilder(job: IJob): Promise<IJobResult> {\n if (job.config.buildType !== IOS_BUILD_TYPES.CLIENT) {\n await ensureCanBuildSdkVersion(job);\n }\n\n const ctx = createBuilderContext(job);\n\n try {\n await initBuilder(ctx);\n\n const { buildType } = job.config;\n\n if (buildType === IOS_BUILD_TYPES.CLIENT) {\n await prepareAdHocBuildCredentials(job);\n }\n\n if ([IOS_BUILD_TYPES.ARCHIVE, IOS_BUILD_TYPES.CLIENT].includes(buildType!)) {\n await buildArchive(ctx, job);\n } else if (buildType === IOS_BUILD_TYPES.SIMULATOR) {\n await buildSimulator(ctx, job);\n } else {\n throw new Error(`Unsupported iOS build type: ${buildType}`);\n }\n\n const artifactUrl = await uploadBuildToS3(ctx);\n return { artifactUrl };\n } catch (err) {\n logErrorOnce(err);\n throw err;\n } finally {\n await cleanup(ctx);\n }\n}\n\nasync function initBuilder(ctx: IContext) {\n for (const dir of getTemporaryDirs(ctx)) {\n await fs.ensureDir(dir);\n await fs.chmod(dir, 0o755);\n }\n}\n\nasync function cleanup(ctx: IContext) {\n if (config.builder.skipCleanup) {\n return;\n }\n await Promise.all(getTemporaryDirs(ctx).map((dir: string) => fs.remove(dir)));\n}\n\nconst getTemporaryDirs = (ctx: IContext) =>\n Object.values(pick(ctx, ['appDir', 'provisioningProfileDir'])) as string[];\n"]}
+15
View File
@@ -0,0 +1,15 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const shellAppBuilder_1 = __importDefault(require("../utils/ios/shellAppBuilder"));
const logger_1 = __importDefault(require("../../logger"));
async function buildSimulator(ctx, job) {
const l = logger_1.default.child({ buildPhase: 'running simulator builder' });
l.info('running simulator build');
await shellAppBuilder_1.default(ctx, job);
l.info('build complete');
}
exports.default = buildSimulator;
//# sourceMappingURL=simulator.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"simulator.js","sourceRoot":"","sources":["../../../src/builders/ios/simulator.ts"],"names":[],"mappings":";;;;;AACA,mFAA2E;AAE3E,0DAAmC;AAEpB,KAAK,UAAU,cAAc,CAAC,GAAa,EAAE,GAAS;IACnE,MAAM,CAAC,GAAG,gBAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,2BAA2B,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAClC,MAAM,yBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAC3B,CAAC;AALD,iCAKC","sourcesContent":["import { IContext } from 'turtle/builders/ios/context';\nimport runShellAppBuilder from 'turtle/builders/utils/ios/shellAppBuilder';\nimport { IJob } from 'turtle/job';\nimport logger from 'turtle/logger';\n\nexport default async function buildSimulator(ctx: IContext, job: IJob) {\n const l = logger.child({ buildPhase: 'running simulator builder' });\n l.info('running simulator build');\n await runShellAppBuilder(ctx, job);\n l.info('build complete');\n}\n"]}
@@ -0,0 +1,65 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const fs_extra_1 = __importDefault(require("fs-extra"));
const get_1 = __importDefault(require("lodash/get"));
const v4_1 = __importDefault(require("uuid/v4"));
const sqs = __importStar(require("../../../aws/sqs"));
const build_1 = require("../../../constants/build");
const logger_1 = __importDefault(require("../../../logger"));
const turtleContext_1 = require("../../../turtleContext");
async function getOrCreateCredentials(jobData) {
if (!jobData.credentials) {
const l = logger_1.default.child({ buildPhase: 'generating keystore' });
const credentials = {};
l.info('Creating keystore');
const keystoreFilename = `/tmp/keystore-${jobData.id}.tmp.jks`;
credentials.keystorePassword = v4_1.default().replace(/-/g, '');
credentials.keyPassword = v4_1.default().replace(/-/g, '');
credentials.keystoreAlias = Buffer.from(jobData.experienceName).toString('base64');
const androidPackage = get_1.default(jobData, 'manifest.android.package')
|| get_1.default(jobData, 'config.androidPackage');
if (!androidPackage) {
throw new Error('Android package name is not set in the app manifest (please update app.json if you\'re using turtle-cli).');
}
await xdl_1.AndroidCredentials.createKeystore({
keystorePath: keystoreFilename,
keystorePassword: credentials.keystorePassword,
keyPassword: credentials.keyPassword,
keyAlias: credentials.keystoreAlias,
}, androidPackage);
credentials.keystore = (await fs_extra_1.default.readFile(keystoreFilename)).toString('base64');
l.info('Keystore created successfully');
if (turtleContext_1.isOffline()) {
const projectKeystorePath = path_1.default.join(jobData.projectDir, `${jobData.experienceName}.jks`);
await fs_extra_1.default.copy(keystoreFilename, projectKeystorePath);
l.info(`Saved created keystore to ${projectKeystorePath}`);
l.info(`Keystore password: ${credentials.keystorePassword}`);
l.info(`Keystore alias: ${credentials.keystoreAlias}`);
l.info(`Key password: ${credentials.keyPassword}`);
l.info(`Please keep these credentials safe`);
}
else {
await sqs.sendMessage(jobData.id, build_1.UPDATE_CREDENTIALS, {
...credentials,
});
l.info('Keystore sent to storage successfully');
}
await fs_extra_1.default.unlink(keystoreFilename);
return credentials;
}
return jobData.credentials;
}
exports.default = getOrCreateCredentials;
//# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../../src/builders/utils/android/credentials.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAwB;AAExB,mCAA+C;AAC/C,wDAA0B;AAC1B,qDAA6B;AAC7B,iDAA6B;AAE7B,sDAAsC;AACtC,oDAA4D;AAE5D,6DAAmC;AACnC,0DAAiD;AAEjD,KAAK,UAAU,sBAAsB,CAAC,OAAa;IACjD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;QACxB,MAAM,CAAC,GAAG,gBAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC5B,MAAM,gBAAgB,GAAG,iBAAiB,OAAO,CAAC,EAAE,UAAU,CAAC;QAC/D,WAAW,CAAC,gBAAgB,GAAG,YAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1D,WAAW,CAAC,WAAW,GAAG,YAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrD,WAAW,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnF,MAAM,cAAc,GAClB,aAAG,CAAC,OAAO,EAAE,0BAA0B,CAAC;eACrC,aAAG,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;QAC3C,IAAI,CAAC,cAAc,EAAE;YACnB,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;SACH;QAED,MAAM,wBAAkB,CAAC,cAAc,CACrC;YACE,YAAY,EAAE,gBAAgB;YAC9B,gBAAgB,EAAE,WAAW,CAAC,gBAAgB;YAC9C,WAAW,EAAE,WAAW,CAAC,WAAW;YACpC,QAAQ,EAAE,WAAW,CAAC,aAAa;SACpC,EACD,cAAc,CACf,CAAC;QAEF,WAAW,CAAC,QAAQ,GAAG,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChF,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QACxC,IAAI,yBAAS,EAAE,EAAE;YACf,MAAM,mBAAmB,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,OAAO,CAAC,cAAc,MAAM,CAAC,CAAC;YAC3F,MAAM,kBAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;YACrD,CAAC,CAAC,IAAI,CAAC,6BAA6B,mBAAmB,EAAE,CAAC,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAC,sBAAsB,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;YAC7D,CAAC,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC,aAAa,EAAE,CAAC,CAAC;YACvD,CAAC,CAAC,IAAI,CAAC,iBAAiB,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;SAC9C;aAAM;YACL,MAAM,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,0BAAkB,EAAE;gBACpD,GAAG,WAAW;aACf,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;SACjD;QACD,MAAM,kBAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAClC,OAAO,WAAW,CAAC;KACpB;IAED,OAAO,OAAO,CAAC,WAAkC,CAAC;AACpD,CAAC;AAED,kBAAe,sBAAsB,CAAC","sourcesContent":["import path from 'path';\n\nimport { AndroidCredentials } from '@expo/xdl';\nimport fs from 'fs-extra';\nimport get from 'lodash/get';\nimport uuidv4 from 'uuid/v4';\n\nimport * as sqs from 'turtle/aws/sqs';\nimport { UPDATE_CREDENTIALS } from 'turtle/constants/build';\nimport { IAndroidCredentials, IJob } from 'turtle/job';\nimport logger from 'turtle/logger';\nimport { isOffline } from 'turtle/turtleContext';\n\nasync function getOrCreateCredentials(jobData: IJob): Promise<IAndroidCredentials> {\n if (!jobData.credentials) {\n const l = logger.child({ buildPhase: 'generating keystore' });\n const credentials: any = {};\n l.info('Creating keystore');\n const keystoreFilename = `/tmp/keystore-${jobData.id}.tmp.jks`;\n credentials.keystorePassword = uuidv4().replace(/-/g, '');\n credentials.keyPassword = uuidv4().replace(/-/g, '');\n credentials.keystoreAlias = Buffer.from(jobData.experienceName).toString('base64');\n const androidPackage =\n get(jobData, 'manifest.android.package')\n || get(jobData, 'config.androidPackage');\n if (!androidPackage) {\n throw new Error(\n 'Android package name is not set in the app manifest (please update app.json if you\\'re using turtle-cli).',\n );\n }\n\n await AndroidCredentials.createKeystore(\n {\n keystorePath: keystoreFilename,\n keystorePassword: credentials.keystorePassword,\n keyPassword: credentials.keyPassword,\n keyAlias: credentials.keystoreAlias,\n },\n androidPackage,\n );\n\n credentials.keystore = (await fs.readFile(keystoreFilename)).toString('base64');\n l.info('Keystore created successfully');\n if (isOffline()) {\n const projectKeystorePath = path.join(jobData.projectDir, `${jobData.experienceName}.jks`);\n await fs.copy(keystoreFilename, projectKeystorePath);\n l.info(`Saved created keystore to ${projectKeystorePath}`);\n l.info(`Keystore password: ${credentials.keystorePassword}`);\n l.info(`Keystore alias: ${credentials.keystoreAlias}`);\n l.info(`Key password: ${credentials.keyPassword}`);\n l.info(`Please keep these credentials safe`);\n } else {\n await sqs.sendMessage(jobData.id, UPDATE_CREDENTIALS, {\n ...credentials,\n });\n l.info('Keystore sent to storage successfully');\n }\n await fs.unlink(keystoreFilename);\n return credentials;\n }\n\n return jobData.credentials as IAndroidCredentials;\n}\n\nexport default getOrCreateCredentials;\n"]}
@@ -0,0 +1,17 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xdl_1 = require("@expo/xdl");
const config_1 = __importDefault(require("../../../config"));
const constants_1 = require("../../../constants");
function formatShellAppDirectory({ sdkVersion }) {
const majorSdkVersion = xdl_1.ExponentTools.parseSdkMajorVersion(sdkVersion);
return config_1.default.builder.useLocalWorkingDir
? path_1.default.join(config_1.default.directories.workingDir, 'local')
: path_1.default.join(config_1.default.directories.workingDir, constants_1.PLATFORMS.ANDROID, `sdk${majorSdkVersion}`);
}
exports.formatShellAppDirectory = formatShellAppDirectory;
//# sourceMappingURL=workingdir.js.map
@@ -0,0 +1 @@
{"version":3,"file":"workingdir.js","sourceRoot":"","sources":["../../../../src/builders/utils/android/workingdir.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAExB,mCAA0C;AAG1C,6DAAmC;AACnC,kDAA6C;AAE7C,SAAgB,uBAAuB,CAAC,EAAE,UAAU,EAA4B;IAC9E,MAAM,eAAe,GAAG,mBAAa,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACvE,OAAO,gBAAM,CAAC,OAAO,CAAC,kBAAkB;QACtC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,gBAAM,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC;QACnD,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,gBAAM,CAAC,WAAW,CAAC,UAAU,EAAE,qBAAS,CAAC,OAAO,EAAE,MAAM,eAAe,EAAE,CAAC,CAAC;AAC3F,CAAC;AALD,0DAKC","sourcesContent":["import path from 'path';\n\nimport { ExponentTools } from '@expo/xdl';\n\nimport { IShellAppDirectoryConfig } from 'turtle/builders/utils/workingdir';\nimport config from 'turtle/config';\nimport { PLATFORMS } from 'turtle/constants';\n\nexport function formatShellAppDirectory({ sdkVersion }: IShellAppDirectoryConfig) {\n const majorSdkVersion = ExponentTools.parseSdkMajorVersion(sdkVersion);\n return config.builder.useLocalWorkingDir\n ? path.join(config.directories.workingDir, 'local')\n : path.join(config.directories.workingDir, PLATFORMS.ANDROID, `sdk${majorSdkVersion}`);\n}\n"]}
+33
View File
@@ -0,0 +1,33 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const url = __importStar(require("url"));
const config_1 = __importDefault(require("../../config"));
const logger_1 = __importDefault(require("../../logger"));
function getExperienceUrl(experienceName, publicUrl) {
// publicUrl is passed in if user wants to build an externally hosted app
if (publicUrl) {
return publicUrl;
}
const { protocol, hostname, port } = config_1.default.api;
return url.format({ protocol, hostname, port, pathname: `/${experienceName}` });
}
exports.getExperienceUrl = getExperienceUrl;
const alreadyLoggedError = Symbol('alreadyLoggedError');
function logErrorOnce(err) {
if (!err[alreadyLoggedError]) {
logger_1.default.error(err.stack);
err[alreadyLoggedError] = true;
}
}
exports.logErrorOnce = logErrorOnce;
//# sourceMappingURL=common.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/builders/utils/common.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yCAA2B;AAE3B,0DAAmC;AACnC,0DAAmC;AAEnC,SAAgB,gBAAgB,CAAC,cAAsB,EAAE,SAAkB;IACzE,yEAAyE;IACzE,IAAI,SAAS,EAAE;QACb,OAAO,SAAS,CAAC;KAClB;IACD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,gBAAM,CAAC,GAAG,CAAC;IAChD,OAAO,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,cAAc,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC;AAPD,4CAOC;AAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAExD,SAAgB,YAAY,CAAC,GAAQ;IACnC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE;QAC5B,gBAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,GAAG,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;KAChC;AACH,CAAC;AALD,oCAKC","sourcesContent":["import * as url from 'url';\n\nimport config from 'turtle/config';\nimport logger from 'turtle/logger';\n\nexport function getExperienceUrl(experienceName: string, publicUrl?: string) {\n // publicUrl is passed in if user wants to build an externally hosted app\n if (publicUrl) {\n return publicUrl;\n }\n const { protocol, hostname, port } = config.api;\n return url.format({ protocol, hostname, port, pathname: `/${experienceName}` });\n}\n\nconst alreadyLoggedError = Symbol('alreadyLoggedError');\n\nexport function logErrorOnce(err: any) {\n if (!err[alreadyLoggedError]) {\n logger.error(err.stack);\n err[alreadyLoggedError] = true;\n }\n}\n"]}
+12
View File
@@ -0,0 +1,12 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
async function writeBase64ToBinaryFile(filename, base64) {
const buffer = Buffer.from(base64, 'base64');
await fs_extra_1.default.writeFile(filename, buffer);
}
exports.writeBase64ToBinaryFile = writeBase64ToBinaryFile;
//# sourceMappingURL=file.js.map
Loaded 100 of 265 files, more files were not shown because too many files have changed in this diff. Show more