Compare commits

...
Author SHA1 Message Date
Dominik Sokal 9d8a046dd4 update README 2019-08-21 13:53:52 +02:00
Dominik Sokal d29d2b8de0 delete everything 2019-08-21 13:53:48 +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
Dominik Sokal 05b96a5b6f update builders configuration to the current state 2019-06-12 09:55:44 +02:00
Dominik Sokal 5467aca0fb update CHANGELOG 2019-06-11 17:55:17 +02:00
174 changed files with 1 additions and 20622 deletions

No files matched your search

-214
View File
@@ -1,214 +0,0 @@
version: 2.1
executors:
nix: &nix
docker:
- image: lnl7/nix:2.2
# Symlink to the readline-enabled bash which is the default command of the container
shell: /run/current-system/sw/bin/bash -leo pipefail
working_directory: ~/turtle
mac:
macos: # https://circleci.com/docs/2.0/testing-ios/#supported-xcode-versions
xcode: '10.1.0'
working_directory: /Users/distiller/project
shell: /bin/bash -leo pipefail
android:
<<: *nix
resource_class: xlarge
commands:
install_nix:
steps:
- run:
name: Install nix
command: curl https://nixos.org/releases/nix/nix-2.2.1/install | bash -s -- --no-daemon
- run:
name: Add nix-initializing line to .bashrc
command: echo ". ~/.nix-profile/etc/profile.d/nix.sh" >> ~/.bashrc
setup:
steps:
- run:
name: Install common packages
command: |
nix-env -iA \
nixpkgs.binutils \
nixpkgs.curl \
nixpkgs.direnv \
nixpkgs.findutils \
nixpkgs.gawk \
nixpkgs.git \
nixpkgs.gnused \
nixpkgs.gnutar \
nixpkgs.gzip \
nixpkgs.openssh \
nixpkgs.python \
nixpkgs.xz
- run:
name: Configure direnv
command: |
mkdir -p ~/.config/direnv
echo -e "[whitelist]\nprefix = [ \"$HOME\" ]" > ~/.config/direnv/config.toml
echo 'eval "$(direnv export bash)"' >> ~/.bash_profile
- run:
name: Configure yarn
command: echo '--frozen-lockfile true' >> ~/.yarnrc
- checkout
- run:
name: Configure aws-cli
command: |
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
setup_nix:
steps:
- run:
name: Add cp and rm stubs
command: |
cat \<< 'EOF' >> /bin/cp
#! /usr/bin/env bash
/usr/bin/env cp "$@"
EOF
chmod +x /bin/cp
cat \<< 'EOF' >> /bin/rm
#! /usr/bin/env bash
/usr/bin/env rm "$@"
EOF
chmod +x /bin/rm
decrypt_secrets_if_possible:
steps:
- run:
name: Decrypt secrets if possible
command: |
if [[ -z "$TURTLE_GIT_CRYPT_KEY_BASE64" ]]; then
echo 'git-crypt key not present in environment'
else
git crypt unlock <(echo $TURTLE_GIT_CRYPT_KEY_BASE64 | base64 --decode)
fi
restore_yarn_cache:
parameters:
workingdir:
type: string
default: .
steps:
- restore_cache:
key: yarn-v1-{{ checksum "<< parameters.workingdir >>/yarn.lock" }}
save_yarn_cache:
parameters:
workingdir:
type: string
default: .
steps:
- save_cache:
key: yarn-v1-{{ checksum "<< parameters.workingdir >>/yarn.lock" }}
paths:
- ~/.cache/yarn # `yarn cache dir`
restore_workingdir_cache:
parameters:
platform:
type: string
default: ios
sdk_version:
type: string
default: sdk32
steps:
- restore_cache:
key: "workingdir-v1-<< parameters.platform >>-<< parameters.sdk_version >>"
save_workingdir_cache:
parameters:
workingdir:
type: string
default: /Users/distiller/project/workingdir
platform:
type: string
default: ios
sdk_version:
type: string
default: sdk32
steps:
- save_cache:
key: "workingdir-v1-<< parameters.platform >>-<< parameters.sdk_version >>"
paths:
- "<< parameters.workingdir >>/<< parameters.platform >>/<< parameters.sdk_version >>"
jobs:
build:
executor: nix
steps:
- setup
- restore_yarn_cache
- run: yarn
- save_yarn_cache
- run: yarn lint
- run: yarn build
unit_tests:
executor: nix
steps:
- setup
- restore_yarn_cache
- run: yarn
- save_yarn_cache
- run:
name: Run unit tests
command: ./scripts/tests/runUnitTestsCI.sh
ios_smoke_tests:
executor: mac
steps:
- install_nix
- setup
- decrypt_secrets_if_possible
- restore_yarn_cache
- run: yarn
- save_yarn_cache
- restore_workingdir_cache:
sdk_version: sdk32
platform: ios
- run:
name: Run iOS smoke tests
command: ./scripts/tests/runIOSSmokeTestsCI.sh
- save_workingdir_cache:
workingdir: /Users/distiller/project/workingdir
sdk_version: sdk32
platform: ios
android_smoke_tests:
executor: android
steps:
- setup
- setup_nix
- restore_yarn_cache
- run: yarn
- save_yarn_cache
- restore_workingdir_cache:
sdk_version: sdk32
platform: android
- run:
name: Fetch Android shell app
command: SDK_VERSION=sdk32 ./scripts/android/fetchRemoteAndroidTarball.sh
- run:
name: Run Android smoke tests
command: |
nix-shell nix/android-shell.nix --pure \
--run "./scripts/tests/runAndroidSmokeTestsCI.sh"
- save_workingdir_cache:
workingdir: ~/turtle/workingdir
sdk_version: sdk32
platform: android
workflows:
checks:
jobs:
- build
tests:
jobs:
- unit_tests
- ios_smoke_tests
- android_smoke_tests
-23
View File
@@ -1,23 +0,0 @@
#!/usr/bin/env bash
source_local() {
file=./.envrc.local
if [[ -f "$file" ]]; then
source_env $file
fi
watch_file $file
}
source_up || true
source_local
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
fi
-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.
-14
View File
@@ -1,14 +0,0 @@
!/src/node_modules
node_modules
yarn-error.log
google-cloud-credentials.json
/build/
/workingdir/*
/artifacts/*
shell.apk
.secrets*
*.swp
*.swo
-1
View File
@@ -1 +0,0 @@
fixtures/
-1
View File
@@ -1 +0,0 @@
v8.15.1
-9
View File
@@ -1,9 +0,0 @@
{
"git": {
"commit": false,
"tag": true,
"push": true,
"requireUpstream": false,
"tagName": "v${version}"
}
}
-12
View File
@@ -1,12 +0,0 @@
{
"npm": {
"tag": "latest"
},
"git": {
"requireUpstream": false,
"tagName": "v${version}"
},
"github": {
"release": true
}
}
-8
View File
@@ -1,8 +0,0 @@
LOGGER_LEVEL="debug"
API_PROTOCOL="http"
API_HOSTNAME="localhost"
API_PORT="3000"
SENTRY_DSN=""
ENVIRONMENT="development"
REDIS_URL="redis://localhost:6379/0"
REDIS_CONFIG_URL="redis://localhost:6379/0"
-160
View File
@@ -1,160 +0,0 @@
# 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]
### 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.
### 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.
### 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.
### 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.
## [0.4.3] - 2019-01-09
### Changed
- Update iOS shell app for SDK32.
- Update Android shell app for SDK32.
-7
View File
@@ -1,7 +0,0 @@
# Community Code of Conduct
The Expo team is committed to fostering an open and welcoming environment.
**Our Community Guidelines can be found here:**
https://expo.io/guidelines
-33
View File
@@ -1,33 +0,0 @@
# Contributing to Turtle CLI
## How to contribute
You can contribute to Turtle CLI in various ways, including:
- [Reporting bugs or issues](https://github.com/expo/turtle/issues/new) on GitHub. Please make sure to fill in all the details suggested by the template to make sure the issue can be addressed as quickly as possible.
- [Submitting improvements to the documentation](https://github.com/expo/expo/tree/master/docs). Updates, enhancements, new guides, spelling fixes…
- Helping other people on [Expo Forums](https://forums.expo.io/) and on [Expo Developers Slack](http://slack.expo.io).
- Looking at existing [issues](https://github.com/expo/turtle/issues) and adding more information, particularly helping to reproduce the issues.
- [Submitting a pull request](#submitting-a-pull-request) with a bug fix or an improvement.
## Turtle CLI repository
### Codebase
This repository contains the codebase for the `turtle-cli` NPM package. The same codebase is used to run standalone app builders on the Expo servers.
### 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/`.)
2. Write the description of your pull request. Make sure to include a test plan and test your changes.
3. Make sure all tests pass on CircleCI.
4. Wait for a review and adjust the code if necessary.
## Publishing a release
- 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!
-126
View File
@@ -1,126 +0,0 @@
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
ADD . /app/turtle
RUN mv /app/turtle/workingdir /app && \
for SDK_VERSION in `ls /app/workingdir/android/`; do \
echo "preparing $SDK_VERSION shell app" && \
cd /app/workingdir/android/$SDK_VERSION && \
if [ -f universe-package.json ]; then \
mv package.json exponent-package.json && \
mv universe-package.json package.json && \
yarn install && \
mv package.json universe-package.json && \
mv exponent-package.json package.json; \
else \
yarn install; \
fi \
; done && \
mv /app/workingdir /app/turtle
ENV NODE_ENV "production"
ENV TURTLE_WORKING_DIR_PATH /app/turtle/workingdir/
WORKDIR /app/turtle
CMD ["node", "./build/server.js"]
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015-present 650 Industries, Inc. (aka Expo)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1 -43
View File
@@ -1,43 +1 @@
<h3 align=center>
<img src="logo/horizontal.png" width=50%>
</h3>
[![CircleCI](https://img.shields.io/circleci/project/github/expo/turtle/master.svg)](https://circleci.com/gh/expo/turtle)
[![NPM](https://img.shields.io/npm/v/turtle-cli/latest.svg)](https://npmjs.com/package/turtle-cli)
[![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/expo/turtle/blob/master/LICENSE)
[![Expo Developers Slack](https://img.shields.io/badge/Expo%20Developers-e01563.svg?logo=slack)](http://slack.expo.io)
[![Expo Forums](https://img.shields.io/badge/Expo%20Forums-blue.svg)](https://forums.expo.io/)
<hr />
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)
- [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.
- Ask for help in **one** of the following ways:
* create [a GitHub issue](https://github.com/expo/turtle/issues/new).
* create a new topic on [Expo Forums](https://forums.expo.io/).
* 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.
this commit is not really deployed to our builders :(
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env node
'use strict';
const subcommand = process.argv[2];
if (subcommand) {
const [, platform] = subcommand.split(':');
if (platform === 'ios' || platform === 'android') {
// so that logs have correct platform set
process.env.PLATFORM = platform;
}
}
require('source-map-support').install();
require('../build/bin/env').initOfflineEnv();
require('../build/bin/index').run('turtle');
-14
View File
@@ -1,14 +0,0 @@
{
"displayName": "turtle",
"testEnvironment": "node",
"rootDir": "../src",
"moduleNameMapper": {
"^turtle/(.*)$": "<rootDir>/$1"
},
"transform": {
"^.+\\.ts$": "ts-jest"
},
"testRegex": "(test|spec)\\.ts$",
"moduleFileExtensions": ["ts", "js", "json"],
"verbose": true
}
-14
View File
@@ -1,14 +0,0 @@
{
"displayName": "turtle",
"testEnvironment": "node",
"rootDir": "../src",
"moduleNameMapper": {
"^turtle/(.*)$": "<rootDir>/$1"
},
"transform": {
"^.+\\.ts$": "ts-jest"
},
"testMatch": [ "**/__smoke__/*.test.ts" ],
"moduleFileExtensions": ["ts", "js", "json"],
"verbose": true
}
-14
View File
@@ -1,14 +0,0 @@
{
"displayName": "turtle",
"testEnvironment": "node",
"rootDir": "../src",
"moduleNameMapper": {
"^turtle/(.*)$": "<rootDir>/$1"
},
"transform": {
"^.+\\.ts$": "ts-jest"
},
"testMatch": [ "**/__tests__/*.ts" ],
"moduleFileExtensions": ["ts", "js", "json"],
"verbose": true
}
-156
View File
@@ -1,156 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: turtle-android
namespace: ${NAMESPACE}
spec:
replicas: ${REPLICAS}
minReadySeconds: 5
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 5
selector:
matchLabels:
app: turtle-android
environment: ${NAMESPACE}
template:
metadata:
labels:
app: turtle-android
environment: ${NAMESPACE}
spec:
restartPolicy: Always
terminationGracePeriodSeconds: 1200 ## wait 20 minutes for any builds to complete
tolerations:
- key: dedicated
operator: Equal
value: jobs
effect: NoSchedule
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: dedicated
operator: In
values:
- jobs
containers:
- name: turtle-android
image: ${IMAGE}
env:
# static vars
- name: ENVIRONMENT
value: ${NAMESPACE}
- name: PLATFORM
value: android
- name: AWS_S3_BUCKET
value: exp-shell-app-assets
- name: AWS_S3_REGION
value: us-west-1
- name: TURTLE_TEMPORARY_FILES_DIR
value: /tmp/turtle
# vars from k8s secrets
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_access_key_id
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_secret_access_key
- name: AWS_SQS_REGION
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_region
- name: AWS_SQS_IOS_QUEUE_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_ios_queue_url
- name: AWS_SQS_ANDROID_QUEUE_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_android_queue_url
- name: AWS_SQS_IOS_PRIORITY_QUEUE_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_ios_priority_queue_url
- name: AWS_SQS_ANDROID_PRIORITY_QUEUE_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_android_priority_queue_url
- name: AWS_SQS_OUT_QUEUE_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_sqs_out_queue_url
- name: AWS_CLOUDWATCH_REGION
valueFrom:
secretKeyRef:
name: turtle-js-config
key: aws_cloudwatch_region
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: redis_url
- name: REDIS_CONFIG_URL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: turtle_redis_url
- name: SENTRY_DSN
valueFrom:
secretKeyRef:
name: turtle-js-config
key: sentry_dsn
- name: API_PROTOCOL
valueFrom:
secretKeyRef:
name: turtle-js-config
key: api_protocol
- name: API_HOSTNAME
valueFrom:
secretKeyRef:
name: turtle-js-config
key: api_hostname
- name: API_PORT
valueFrom:
secretKeyRef:
name: turtle-js-config
key: api_port
- name: DATADOG_API_KEY
valueFrom:
secretKeyRef:
name: turtle-js-config
key: datadog_api_key
- name: DATADOG_APP_KEY
valueFrom:
secretKeyRef:
name: turtle-js-config
key: datadog_app_key
# other vars
- name: GRADLE_DAEMON_DISABLED
value: "1"
- name: DISABLE_DEX_MAX_HEAP
value: "true"
- name: JAVA_OPTS
value: '-Xms2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+UseG1GC'
- name: GRADLE_OPTS
value: '-Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xms2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+UseG1GC"'
resources:
requests:
memory: "8192Mi"
cpu: "2000m"
limits:
memory: "8192Mi"
cpu: "2000m"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

-228
View File
@@ -1,228 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="151.68256mm"
height="150.14914mm"
viewBox="0 0 151.68255 150.14914"
version="1.1"
id="svg8"
sodipodi:docname="logo-only.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<defs
id="defs2">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath16">
<path
d="M 0,192 H 192 V 0 H 0 Z"
id="path18"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath26">
<path
d="M -4.88281e-4,192 H 192 V -4.88281e-4 H -4.88281e-4 Z"
id="path28"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath34">
<path
d="M -4.88281e-4,192 H 192 V -4.88281e-4 H -4.88281e-4 Z"
id="path36"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath38">
<path
d="M 0,192 H 192 V 0 H 0 Z"
id="path40"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath42">
<path
d="M 0,192 H 192 V 0 H 0 Z"
id="path44"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath116">
<path
d="M 0,192 H 192 V -4.88281e-4 H 0 Z"
id="path118"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath120">
<path
d="M 0,192 H 192 V 4.88281e-4 H 0 Z"
id="path122"
inkscape:connector-curvature="0" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath124">
<path
d="M 192,192 H 0 V 0 h 192 z"
id="path126"
inkscape:connector-curvature="0" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#3d3d3d"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497474"
inkscape:cx="-192.6803"
inkscape:cy="237.87441"
inkscape:document-units="px"
inkscape:current-layer="layer2"
showgrid="false"
units="mm"
inkscape:showpageshadow="false"
inkscape:window-width="1366"
inkscape:window-height="705"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:object-paths="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
transform="translate(-29.1587,91.282943)">
<g
id="g6678"
transform="translate(792.65276,-237.50395)">
<path
inkscape:connector-curvature="0"
id="path6638"
d="m -687.31547,152.53653 -16.98554,9.86968 v 19.204 l 15.52774,-8.98033 a 2.9187589,2.9239263 0 0 1 1.52654,-0.38809 2.9187589,2.9239263 0 0 1 1.39009,0.38809 l 15.52721,8.98033 v -19.204 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<path
inkscape:connector-curvature="0"
id="path6640"
d="m -687.3165,178.53959 -48.20947,27.88306 v 55.7661 l 48.20947,27.88306 48.20996,-27.88306 v -55.7661 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<path
inkscape:connector-curvature="0"
id="path6642"
d="m -738.44361,184.99346 -16.985,9.86968 v 19.74092 l 14.06631,8.17418 v -18.04386 a 2.9187589,2.9239263 0 0 1 1.45986,-2.5337 l 15.57269,-9.00617 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<path
inkscape:connector-curvature="0"
id="path6644"
d="m -634.61997,184.99346 -14.89522,8.65426 14.78772,8.55296 a 2.9187589,2.9239263 0 0 1 1.45986,2.5337 v 18.95491 l 15.63418,-9.08523 v -19.74092 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<path
inkscape:connector-curvature="0"
id="path6646"
d="m -741.3623,245.97166 -16.30752,9.47642 v 19.74091 l 16.98398,9.87124 16.47753,-9.57513 -15.69413,-9.07748 a 2.9187589,2.9239263 0 0 1 -1.45986,-2.5306 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<path
inkscape:connector-curvature="0"
id="path6648"
d="m -633.26761,247.66664 v 16.21038 a 2.9187589,2.9239263 0 0 1 -1.45986,2.5306 l -17.35915,10.0397 v 5.2e-4 l 0.20309,-0.11782 15.02182,8.73022 16.98655,-9.87124 v -19.74091 z"
style="opacity:1;fill:#00002f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.32291651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
<g
id="g6654"
transform="translate(-172.35714,278.19048)">
<path
inkscape:connector-curvature="0"
id="path6650"
d="m -514.88984,-105.94886 a 2.918759,2.9239263 0 0 0 -1.52625,0.388 l -51.12915,29.57121 a 2.918759,2.9239263 0 0 0 -1.45977,2.5338 v 59.142302 a 2.918759,2.9239263 0 0 0 1.45977,2.530901 l 51.12915,29.571197 a 2.918759,2.9239263 0 0 0 2.91661,0 l 51.12917,-29.571197 a 2.918759,2.9239263 0 0 0 1.45977,-2.530901 V -73.45585 a 2.918759,2.9239263 0 0 0 -1.45977,-2.5338 l -51.12917,-29.57121 a 2.918759,2.9239263 0 0 0 -1.39036,-0.388 z m -0.0694,6.298204 48.20963,27.882906 v 55.766001 l -48.20963,27.883001 -48.20965,-27.883001 V -71.76775 Z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17500019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
id="path6652"
d="m -514.88885,-85.717946 a 2.9118515,2.9308623 0 0 0 -1.52531,0.3904 l -33.47339,19.451796 a 2.9118515,2.9308623 0 0 0 -1.45528,2.5391 v 38.903402 a 2.9118515,2.9308623 0 0 0 1.45528,2.537198 l 33.47339,19.4517023 a 2.9118515,2.9308623 0 0 0 2.91246,0 l 33.47151,-19.4517023 a 2.9118515,2.9308623 0 0 0 1.45528,-2.537198 V -63.33665 a 2.9118515,2.9308623 0 0 0 -1.45528,-2.5391 l -33.47151,-19.451796 a 2.9118515,2.9308623 0 0 0 -1.38715,-0.3904 z m -0.0699,6.312396 30.56093,17.760299 V -26.12465 L -514.95875,-8.3663467 -545.5197,-26.12665 v -35.518601 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17500019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<g
id="g6660"
transform="translate(-172.35714,278.19048)">
<path
id="path6656"
d="m -519.66912,-32.288849 -5.84307,5.844 h 25.07044 a 2.9220001,2.9220001 0 0 0 0,-5.844 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#45eba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6658"
d="m -529.50808,-61.355249 a 2.9213416,2.9213416 0 0 0 -2.0341,5.017 l 12.45256,12.452501 -12.45256,12.452599 a 2.9213416,2.9213416 0 1 0 4.1329,4.129201 l 14.51539,-14.515401 a 2.9213416,2.9213416 0 0 0 0,-4.1328 l -14.51539,-14.515401 a 2.9213416,2.9213416 0 0 0 -2.0988,-0.887699 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#45eba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17500019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<g
id="g6676"
transform="translate(-172.35714,278.19048)">
<g
id="g6672">
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -514.89008,-131.96866 a 2.9118515,2.9308623 0 0 0 -1.52426,0.3917 l -19.89585,11.5625 a 2.9118515,2.9308623 0 0 0 -1.45673,2.5388 v 23.125004 a 2.9118515,2.9308623 0 0 0 0.18924,1.02881 l 5.63388,-3.25861 v -19.203604 l 16.98527,-9.87 16.98619,9.87 v 19.203604 l 5.6348,3.25861 a 2.9118515,2.9308623 0 0 0 0.18734,-1.02881 v -23.125004 a 2.9118515,2.9308623 0 0 0 -1.4558,-2.5388 l -19.89678,-11.5625 a 2.9118515,2.9308623 0 0 0 -1.3873,-0.3917 z"
id="path6662" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -566.01799,-99.511956 a 2.9118515,2.9308623 0 0 0 -1.52421,0.3918 l -19.89585,11.56251 a 2.9118515,2.9308623 0 0 0 -1.45673,2.5387 v 23.124998 a 2.9118515,2.9308623 0 0 0 1.45673,2.537899 l 18.43343,10.7124 v -6.768201 l -14.06704,-8.174598 v -19.740898 l 16.98522,-9.8699 14.11368,8.2012 5.83733,-3.3766 -18.49521,-10.74751 a 2.9118515,2.9308623 0 0 0 -1.38735,-0.3918 z"
id="path6664" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -462.19425,-99.511956 a 2.9118515,2.9308623 0 0 0 -1.52421,0.3918 l -19.27591,11.20211 5.83641,3.3755 14.89526,-8.6547 16.98619,9.8699 v 19.740898 l -15.63409,9.085498 v 6.765401 a 2.9118515,2.9308623 0 0 0 0.10365,-0.058 l 19.89775,-11.5625 a 2.9118515,2.9308623 0 0 0 1.45483,-2.537801 v -23.124996 a 2.9118515,2.9308623 0 0 0 -1.45483,-2.5388 l -19.89775,-11.56251 a 2.9118515,2.9308623 0 0 0 -1.3873,-0.3918 z"
id="path6666" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -569.00462,-38.844049 a 2.9118515,2.9308623 0 0 0 -0.77875,0.308999 l -19.89683,11.562501 a 2.9118515,2.9308623 0 0 0 -1.45672,2.538801 v 23.1250003 a 2.9118515,2.9308623 0 0 0 1.45672,2.537801 l 19.89683,11.5624977 a 2.9118515,2.9308623 0 0 0 2.91058,0 l 19.89775,-11.5624977 a 2.9118515,2.9308623 0 0 0 0.77778,-0.66460201 l -5.65379,-3.26999799 -16.47749,9.575199 -16.98435,-9.8709 V -22.74215 l 16.30827,-9.477299 z"
id="path6668" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17499971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -460.9106,-37.293149 v 6.769201 l 13.39292,7.781798 v 19.7409023 l -16.9862,9.8709 -15.02174,-8.729901 -5.83733,3.375502 19.40327,11.2762977 a 2.9118515,2.9308623 0 0 0 2.91155,0 l 19.89678,-11.5624977 a 2.9118515,2.9308623 0 0 0 1.4558,-2.537801 V -24.433748 a 2.9118515,2.9308623 0 0 0 -1.4558,-2.538801 z"
id="path6670" />
</g>
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#21aba5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17500019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -531.46275,-116.06384 -0.48112,0.27957 v 5.56039 a 2.9213415,2.9213415 0 0 0 0.0171,0 h 33.93644 a 2.9213415,2.9213415 0 0 0 0.0181,-5.2e-4 v -5.55987 l -0.48109,-0.27957 z"
id="path6674"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

-5
View File
@@ -1,5 +0,0 @@
self: super:
{
nodejs = super.nodejs-8_x;
}
-50
View File
@@ -1,50 +0,0 @@
with (import ./default.nix {});
let
ndk = androidenv.androidndk_17c.override { fullNDK = true; };
ndk_root = "${ndk}/libexec/${ndk.name}";
sdk_path = if stdenv.isDarwin
then "/Library/Android/sdk"
else "/Android/Sdk"; # intentional Capital S
in
mkShell rec {
LANG="en_US.UTF-8";
JAVA_HOME=openjdk8;
ANDROID_SDK_ROOT=builtins.getEnv("HOME") + sdk_path;
ANDROID_NDK_ROOT="${ANDROID_SDK_ROOT}/ndk-bundle";
ANDROID_HOME=ANDROID_SDK_ROOT;
ANDROID_NDK=ANDROID_NDK_ROOT;
nativeBuildInputs = [
awscli
curl
git
nodejs-8_x
openjdk8
yarn
];
passthru = { inherit ndk; };
shellHook = ''
${./install-ndk-17c.sh} ${ndk} ${ndk_root}
yes | ${androidenv.androidsdk_9_0}/bin/sdkmanager --licenses --sdk_root="$ANDROID_SDK_ROOT"
yes | ${androidenv.androidsdk_9_0}/bin/sdkmanager --sdk_root="$ANDROID_SDK_ROOT" "platforms;android-28" | grep -v =
yes | ${androidenv.androidsdk_9_0}/bin/sdkmanager --sdk_root="$ANDROID_SDK_ROOT" "build-tools;28.0.3" | grep -v =
${lib.optionalString stdenv.isLinux ''
for dep in lib lib64; do
if [ -L /$dep ] || [ ! -e /$dep ]; then
echo "Creating /$dep"
ln -s ${stdenv.cc.libc}/$dep /$dep
else
echo "Using existing /$dep"
fi
done
''}
'';
}
-19
View File
@@ -1,19 +0,0 @@
let
pin = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
nixpkgs = builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs-channels/archive/${pin.rev}.tar.gz";
inherit (pin) sha256;
};
in
{ ... } @ args:
import nixpkgs (args // {
config = {
allowUnfree = true;
android_sdk.accept_license = true;
};
overlays = [ (import ./all-packages.nix) ];
})
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
scriptdir="$(dirname ${BASH_SOURCE[0]})"
shellnix="$scriptdir/android-shell.nix"
ndk=${1:-$(nix-build "$shellnix" -A ndk --no-out-link)}
ndkRoot=${2:-$(nix eval --file "$shellnix" --raw ANDROID_NDK_ROOT)}
mkdir -p "$ANDROID_NDK_ROOT" # Create full path if necessary
# Replace any existing link or directory with link
rm -r "$ANDROID_NDK_ROOT"
ln -sn "$ndkRoot" "$ANDROID_NDK_ROOT"
-7
View File
@@ -1,7 +0,0 @@
{
"url": "https://github.com/NixOS/nixpkgs-channels.git",
"rev": "80738ed9dc0ce48d7796baed5364eef8072c794d",
"date": "2018-11-17T11:18:10+01:00",
"sha256": "0anmvr6b47gbbyl9v2fn86mfkcwgpbd5lf0yf3drgm8pbv57c1dc",
"fetchSubmodules": false
}
-6
View File
@@ -1,6 +0,0 @@
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/**/*.test.ts"],
"exec": "ts-node -r tsconfig-paths/register --files src/server.ts"
}
-143
View File
@@ -1,143 +0,0 @@
{
"name": "turtle-cli",
"version": "0.8.2",
"description": "The command-line tool for building standalone Expo apps",
"preferGlobal": true,
"scripts": {
"start": "EXPENV_OVERRIDES=local-common,local,local-queue expenv nodemon | bunyan -o short -l debug --color",
"start:ios": "PLATFORM=ios yarn start",
"start:android": "PLATFORM=android yarn start",
"bin:turtle": "./bin/turtle.js",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"lint:fix": "yarn lint --fix",
"prepare": "rimraf ./build && yarn build",
"build": "ttsc",
"build:production": "./scripts/build.sh",
"secrets:init-private": "./scripts/initPrivateSecrets.sh",
"set-workingdir:remote": "./scripts/setWorkingdirMode.sh remote",
"set-workingdir:local": "./scripts/setWorkingdirMode.sh local",
"docker:pull": "retry5 gcloud docker -- pull gcr.io/exponentjs/turtle-android:latest",
"docker:pull:tag": "retry5 gcloud docker -- pull gcr.io/exponentjs/turtle-android:${TAG}",
"docker:build": "yarn build:production android && gcloud docker -- build -t gcr.io/exponentjs/turtle-android:latest -t gcr.io/exponentjs/turtle-android:${TAG} .",
"docker:push": "retry5 gcloud docker -- push gcr.io/exponentjs/turtle-android:${TAG} && retry5 gcloud docker -- push gcr.io/exponentjs/turtle-android:latest",
"deploy:android": "./scripts/android/deploy.sh",
"test": "yarn jest",
"test:integration": "yarn test --config jest/integration-config.json",
"test:unit": "yarn test --config jest/unit-config.json",
"test:smoke": "yarn test --config jest/smoke-config.json --forceExit",
"test:smoke:android": "PLATFORM=android yarn test:smoke --testNamePattern=android",
"test:smoke:ios": "PLATFORM=ios yarn test:smoke --testNamePattern=iOS",
"release": "./scripts/release.sh",
"release:beta": "./scripts/releaseBeta.sh",
"ssh:android:pods-names": "./scripts/ssh/findAndroidPods.sh",
"ssh:android:connect": "./scripts/ssh/connectToAndroidPod.sh",
"ssh:ios:ips": "./scripts/ssh/findIosIps.sh",
"set-priorities": "yarn set-priorities:local",
"set-priorities:default": "expenv ts-node -r tsconfig-paths/register --files src/scripts/setConfigurations.ts",
"set-priorities:local": "EXPENV_OVERRIDES=local-common,local,local-queue yarn set-priorities:default",
"set-priorities:staging": "yarn set-priorities:default",
"set-priorities:production": "EXPENV_OVERRIDES=prod yarn set-priorities:default",
"set-replica-count:default": "expenv ts-node -r tsconfig-paths/register --files src/scripts/setReplicaCount.ts | bunyan -o short -l debug",
"set-replica-count:local": "EXPENV_OVERRIDES=local-common,local,local-queue yarn set-replica-count:default",
"set-replica-count:staging": "yarn set-replica-count:default",
"set-replica-count:production": "EXPENV_OVERRIDES=prod yarn set-replica-count:default"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.ts": [
"yarn lint:fix",
"git add"
]
},
"bin": {
"turtle": "./bin/turtle.js"
},
"files": [
"bin",
"build",
"scripts/cli",
"shellTarballs"
],
"keywords": [
"expo",
"react-native"
],
"engines": {
"node": ">=8"
},
"author": "Expo <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/expo/turtle/issues"
},
"homepage": "https://github.com/expo/turtle#readme",
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"devDependencies": {
"@types/decompress": "^4.2.3",
"@types/fs-extra": "^5.0.4",
"@types/jest": "^23.3.9",
"@types/joi": "^13.4.3",
"@types/lodash": "^4.14.129",
"@types/progress": "^2.0.1",
"@types/raven": "^2.5.1",
"@types/request": "^2.47.1",
"@types/semver": "^6.0.0",
"@types/sharp": "^0.17.8",
"@types/tar": "^4.0.0",
"@types/uuid": "^3.4.3",
"@types/which": "^1.3.1",
"husky": "^1.3.1",
"jest": "^23.6.0",
"lint-staged": "^8.1.5",
"nock": "^10.0.1",
"nodemon": "^1.18.11",
"release-it": "^10.0.0",
"rimraf": "^2.6.2",
"ts-jest": "^23.10.4",
"ts-node": "^8.0.3",
"ts-transformer-imports": "^0.4.1",
"tsconfig-paths": "^3.8.0",
"tslint": "^5.10.0",
"tslint-eslint-rules": "^5.4.0",
"ttypescript": "^1.5.6",
"typescript": "^3.4.2"
},
"dependencies": {
"@expo/spawn-async": "^1.4.2",
"@expo/xdl": "54.1.4",
"@google-cloud/logging-bunyan": "^0.9.5",
"async-retry": "^1.2.1",
"aws-sdk": "^2.226.1",
"bunyan": "^1.8.12",
"bunyan-debug-stream": "^1.0.8",
"bunyan-sentry-stream": "^1.2.1",
"commander": "^2.15.1",
"copy": "^0.3.1",
"decompress": "^4.2.0",
"dogapi": "^2.8.3",
"fs-extra": "^6.0.0",
"ioredis": "^3.2.2",
"is-semver": "^1.0.8",
"joi": "^13.2.0",
"lodash": "^4.17.11",
"progress": "^2.0.0",
"raven": "^2.6.2",
"request": "^2.88.0",
"request-progress": "^3.0.0",
"semver": "^6.0.0",
"sharp": "^0.21.0",
"source-map-support": "^0.5.6",
"tar": "^4.4.6",
"uuid": "^3.2.1",
"which": "^1.3.1"
},
"optionalDependencies": {
"@expo/traveling-fastlane-darwin": "1.9.4"
}
}
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env bash
set -xeuo pipefail
environment=$1
retry5 gcloud container images add-tag "${IMAGE}:${PREV_TAG}" "${IMAGE}:${CURRENT_TAG}"
export TAG="${CURRENT_TAG}"
nix run expo.k8s-services.turtle.${environment}.deploy --command deploy
@@ -1,4 +0,0 @@
#!/usr/bin/env bash
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
$ROOT_DIR/scripts/fetchRemoteTarballs.sh android
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env bash
set -xeo pipefail
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
if [ -z "$1" ]; then
echo "Please specify a platform to build"
exit 1
fi
PLATFORM=$1
yarn
yarn run build
if [ "$PLATFORM" = "android" ]; then
$ROOT_DIR/scripts/android/fetchRemoteAndroidTarball.sh
elif [ "$PLATFORM" = "ios" ]; then
$ROOT_DIR/scripts/ios/fetchRemoteIosTarball.sh
fi
if [[ -z "${TARBALL}" ]]; then
echo "TARBALL is not set, building tarball skipped"
else
tar zcf "$TARBALL" \
workingdir \
build \
scripts \
package.json \
node_modules \
yarn.lock \
tsconfig.json \
gulpfile.js
fi
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
SDKMANAGER=$ANDROID_HOME/tools/bin/sdkmanager
yes | $SDKMANAGER --licenses > /dev/null
yes | $SDKMANAGER "platforms;android-28"
yes | $SDKMANAGER "platform-tools"
yes | $SDKMANAGER "build-tools;28.0.3"
yes | $SDKMANAGER \
"extras;android;m2repository" \
"extras;google;m2repository" \
"extras;google;google_play_services"
-38
View File
@@ -1,38 +0,0 @@
#!/usr/bin/env bash
set -xeo pipefail
PLATFORM=$1
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
ARTIFACTS_DIR="$ROOT_DIR/artifacts"
WORKING_DIR="$ROOT_DIR/workingdir/$PLATFORM"
SHELL_TARBALLS_DIRECTORY="$ROOT_DIR/shellTarballs/$PLATFORM"
mkdir -p $ARTIFACTS_DIR
convert_s3_to_https() {
BUCKET=`echo $1 | sed 's/s3:\/\/\([^/]*\).*/\1/'`
KEY=`echo $1 | sed 's/s3:\/\/[^/]*\/\(.*\)/\1/'`
echo "https://s3.amazonaws.com/$BUCKET/$KEY"
}
download_shell_app() {
SDK_VERSION=$1
mkdir -p $WORKING_DIR/$SDK_VERSION
TARBALL_S3_URL=$(head -n 1 $SHELL_TARBALLS_DIRECTORY/$SDK_VERSION)
TARBALL_HTTPS_URL=$(convert_s3_to_https $TARBALL_S3_URL)
curl -s $TARBALL_HTTPS_URL -o $ARTIFACTS_DIR/$SDK_VERSION.tar.gz
tar zxf $ARTIFACTS_DIR/$SDK_VERSION.tar.gz -C $WORKING_DIR/$SDK_VERSION
rm -rf $ARTIFACTS_DIR/$SDK_VERSION.tar.gz
}
if [[ -z "$SDK_VERSION" ]]; then
for SDK_VERSION in `ls $SHELL_TARBALLS_DIRECTORY`; do
download_shell_app $SDK_VERSION
done
else
if [ ! -d "$WORKING_DIR/$SDK_VERSION" ]; then
download_shell_app $SDK_VERSION
fi
fi
-25
View File
@@ -1,25 +0,0 @@
#!/usr/bin/env bash
if [ -z "$EXPO_UNIVERSE_DIR" ]; then
echo "You need to specify EXPO_UNIVERSE_DIR to use this script. Alternatively you can create .secrets.local-queue file yourself with AWS_SQS_ANDROID_QUEUE_URL, AWS_SQS_IOS_QUEUE_URL and AWS_SQS_OUT_QUEUE_URL variables."
exit 1
fi
if [ -z "$1" ]; then
echo "Please specify a nickname you used to create AWS SQS queues"
exit 1
fi
TURTLE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
TERRAFORM_DIR="${EXPO_UNIVERSE_DIR}/terraform"
ANDROID=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_android_in | head -1 | cut -d"=" -f2 | xargs`
IOS=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_ios_in | head -1 | cut -d"=" -f2 | xargs`
OUT=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_out | head -1 | cut -d"=" -f2 | xargs`
cat << EOF > $TURTLE_DIR/.secrets.local-queue
AWS_SQS_ANDROID_QUEUE_URL="$ANDROID"
AWS_SQS_IOS_QUEUE_URL="$IOS"
AWS_SQS_OUT_QUEUE_URL="$OUT"
EOF
-4
View File
@@ -1,4 +0,0 @@
#!/usr/bin/env bash
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
$ROOT_DIR/scripts/fetchRemoteTarballs.sh ios
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
$ROOT_DIR/node_modules/.bin/release-it
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!!! PLEASE REMEMBER TO UPDATE CHANGELOG !!!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
$ROOT_DIR/node_modules/.bin/release-it -c $ROOT_DIR/.release-it.beta.json --preRelease=beta
-98
View File
@@ -1,98 +0,0 @@
#!/usr/bin/env bash
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
DOWNLOAD_DIR="${EXPO_DOWNLOAD_DIR:-$HOME/Downloads}"
mkdir -p $DOWNLOAD_DIR
if [ ! -f "$ROOT_DIR/.secrets.local-queue" ]; then
echo "You need to run \"yarn secrets:init-private [SQS_NAME]\" or create .secrets.local-queue file yourself with AWS_SQS_ANDROID_QUEUE_URL, AWS_SQS_IOS_QUEUE_URL and AWS_SQS_OUT_QUEUE_URL variables."
exit 1
fi
setup_local() {
ensure_link_exists() {
if [ ! -L "$2" ]; then
ln -s $1 $2
echo "$2 link created"
fi
}
WORKINGDIR="$ROOT_DIR/workingdir/local"
if [[ -d $WORKINGDIR ]]; then
echo "Local workingdir already prepared"
return
fi
if [[ -z "$EXPO_UNIVERSE_DIR" ]]; then
echo "EXPO_UNIVERSE_DIR needs to be set"
exit -1
fi
cd $EXPO_UNIVERSE_DIR/exponent && yarn
cd $EXPO_UNIVERSE_DIR/exponent/tools-public && yarn && ./generate-dynamic-macros-android.sh
mkdir -p $WORKINGDIR
echo "$WORKINGDIR directory created"
LINKS=("template-files" "package.json" "android" "expokit-npm-package" "packages" "client-builds" "cpp" "exponent-view-template" "ios" "shellAppBase-builds" "shellAppWorkspaces" "node_modules")
for LINKNAME in ${LINKS[@]}; do
ensure_link_exists "$EXPO_UNIVERSE_DIR/exponent/$LINKNAME" "$WORKINGDIR/$LINKNAME"
done
}
setup_remote() {
if [[ -d $ROOT_DIR/workingdir/android && -d $ROOT_DIR/workingdir/ios ]]; then
echo "Shell apps already fetched"
else
echo "Fetching shell apps"
if [ "$PLATFORM" != 'ios' ]; then
$ROOT_DIR/scripts/android/fetchRemoteAndroidTarball.sh
fi
if [ "$PLATFORM" != 'android' ]; then
$ROOT_DIR/scripts/ios/fetchRemoteIosTarball.sh
fi
fi
for sdk in $ROOT_DIR/workingdir/android/* ; do
if [[ -f "$sdk/universe-package.json" ]]; then
mv $sdk/package.json $sdk/exponent-package.json
mv $sdk/universe-package.json $sdk/package.json
cd $sdk && yarn
else
if [[ -f "$sdk/package.json" ]]; then
cd $sdk && yarn
fi
fi
done
}
switch_local() {
cat << EOF > $ROOT_DIR/.secrets.local
TURTLE_FAKE_UPLOAD="1"
TURTLE_FAKE_UPLOAD_DIR="$HOME/Downloads"
TURTLE_WORKING_DIR_PATH="$ROOT_DIR/workingdir"
TURTLE_USE_LOCAL_WORKING_DIR="1"
EOF
}
switch_remote() {
cat << EOF > $ROOT_DIR/.secrets.local
TURTLE_FAKE_UPLOAD="1"
TURTLE_FAKE_UPLOAD_DIR="$HOME/Downloads"
TURTLE_WORKING_DIR_PATH="$ROOT_DIR/workingdir"
EOF
}
if [ "$1" == "local" ]; then
setup_local
switch_local
elif [ "$1" == "remote" ]; then
setup_remote
switch_remote
else
echo "You need to pass remote or local as argument"
exit -1
fi
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env bash
if [ -z "$1" ]; then
echo "Please provide an environment name as a first argument"
exit 1
fi
if [ -z "$2" ]; then
echo "Please provide a pod name as a second argument"
exit 1
fi
kubectl --namespace $1 exec -it $2 -- /bin/bash
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env bash
ENVIRONMENT=${1:-production}
kubectl get pods --namespace $ENVIRONMENT | grep "turtle-android-" | sed -e "s/ */ /g" | cut -d" " -f1
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env bash
ENVIRONMENT=${1:-production}
govc vm.ip -wait 5s turtle-js-"${ENVIRONMENT}"-*
-26
View File
@@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -ueo pipefail
export NODE_ENV=test
export ENVIRONMENT="development"
export AWS_ACCESS_KEY_ID="aws_id"
export AWS_SECRET_ACCESS_KEY="secret"
export AWS_SQS_ANDROID_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_android_in.fifo"
export AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_android_in_priority.fifo"
export AWS_SQS_IOS_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_ios_in.fifo"
export AWS_SQS_IOS_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_ios_in_priority.fifo"
export AWS_SQS_OUT_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_out.fifo"
export AWS_SQS_REGION="aws.west2"
export AWS_S3_BUCKET="exp-shell-app-assets"
export AWS_S3_REGION="us-west-1"
export AWS_CLOUDWATCH_REGION="us-west-1"
export API_PROTOCOL="http"
export API_HOSTNAME="staging.expo.io"
export API_PORT="443"
export REDIS_URL="noop"
export REDIS_CONFIG_URL="noop"
export DATADOG_DISABLED="true"
yarn test:smoke:android
-27
View File
@@ -1,27 +0,0 @@
#!/usr/bin/env bash
set -ueo pipefail
export NODE_ENV=test
export ENVIRONMENT="development"
export AWS_SQS_ANDROID_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_android_in.fifo"
export AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_android_in_priority.fifo"
export AWS_SQS_IOS_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_ios_in.fifo"
export AWS_SQS_IOS_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_ios_in_priority.fifo"
export AWS_SQS_OUT_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_dominik_out.fifo"
export AWS_SQS_REGION="aws.west2"
export AWS_S3_BUCKET="exp-shell-app-assets"
export AWS_S3_REGION="us-west-1"
export AWS_CLOUDWATCH_REGION="us-west-1"
export API_PROTOCOL="https"
export API_HOSTNAME="staging.expo.io"
export API_PORT="443"
export REDIS_URL="noop"
export REDIS_CONFIG_URL="noop"
export DATADOG_DISABLED="true"
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
SDK_VERSION=sdk32 $ROOT_DIR/scripts/ios/fetchRemoteIosTarball.sh
yarn test:smoke:ios
-26
View File
@@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -ueo pipefail
export NODE_ENV=test
export ENVIRONMENT="development"
export AWS_SQS_IOS_QUEUE_URL="noop"
export AWS_SQS_ANDROID_QUEUE_URL="noop"
export AWS_SQS_IOS_PRIORITY_QUEUE_URL="noop"
export AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="noop"
export AWS_SQS_OUT_QUEUE_URL="noop"
export AWS_ACCESS_KEY_ID="noop"
export AWS_SECRET_ACCESS_KEY="noop"
export AWS_SQS_REGION="noop"
export AWS_S3_BUCKET="noop"
export AWS_S3_REGION="noop"
export AWS_CLOUDWATCH_REGION="noop"
export API_PROTOCOL="https"
export API_HOSTNAME="noop"
export API_PORT="443"
export REDIS_URL="noop"
export REDIS_CONFIG_URL="noop"
export DATADOG_DISABLED="true"
yarn test:unit
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-89b2d24c86737d5a489c6a18467e31b2f9ce9005.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-f796aaffa0b5715079b2950faf26c2ff4e53e4c0.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/android-shell-builder-e244e865ed8cb8e20d29ea00b6373845d1c61068.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-expo-client-a2b1e16f330b36fa0dc627a76caabe4d2ff45f77.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-27-db356a09877642d64023af98e4e2e1e632fbe4df.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-28-db356a09877642d64023af98e4e2e1e632fbe4df.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-29-db356a09877642d64023af98e4e2e1e632fbe4df.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-30-6863276e6b9605e31228c845a047387571959e9b.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-latest-e1a8bd0ab2e1eba546792c0ffc282b5b202ccc39.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-latest-dc981c7110b7d508de8e9c352064dc3d745c9f72.tar.gz
-1
View File
@@ -1 +0,0 @@
s3://exp-artifacts/ios-shell-builder-sdk-latest-a2b1e16f330b36fa0dc627a76caabe4d2ff45f77.tar.gz
@@ -1 +0,0 @@
[{"scope":"https://sqs.us-west-2.amazonaws.com:443","method":"POST","path":"/","body":"Action=ReceiveMessage&MaxNumberOfMessages=1&QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F274251141632%2Fturtle_jobs_local_dominik_android_in_priority.fifo&Version=2012-11-05&VisibilityTimeout=30","status":200,"response":"<?xml version=\"1.0\"?><ReceiveMessageResponse xmlns=\"http://queue.amazonaws.com/doc/2012-11-05/\"><ReceiveMessageResult><Message><MessageId>fc2fe53d-1447-4304-90e0-60b025ac9687</MessageId><ReceiptHandle>AQEBcOA9S4yhL3ZCaho9Cv+XVqJEbhOaaWJTsOvBD9SOa/NK/248s0+yI9bHro5Ti9WJrnD3H65SdK9eOETFeS/QDaaCMTYkxjvH/1DrSJt2rAptgItmxl8F6N3iDYLqplOQjmautdjCWYXrCLxMDihMHEjcvWNAq0XLAAjlQJvtm5Z8Vji5xXKJP3IpQOV2DvhS/Cqriteaqe6NW5xKwgKHOC52IVTPMSHiJ0ERUf55agntOOJJ7Za7vHdTr+Zjrxl6yVFWKC/cpwYI00OKGj4bArud0buiaD0rtjszLmcPgcwADRsmhfG65p3gLwIwjfclHqSLlmcuY3c+xsu/5VM1YA==</ReceiptHandle><MD5OfBody>c9e8a99bf73407dfa26a2cb81103c26a</MD5OfBody><Body>{&quot;id&quot;:&quot;b9f9f814-5603-4dd5-929d-c9eed756c591&quot;,&quot;experienceId&quot;:&quot;531b2db0-4b14-11e9-92d6-95aebd1034a3&quot;,&quot;experienceName&quot;:&quot;@dsokal-local/turtle-cli-example&quot;,&quot;platform&quot;:&quot;android&quot;,&quot;config&quot;:{&quot;releaseChannel&quot;:&quot;default&quot;},&quot;status&quot;:&quot;sent-to-queue&quot;,&quot;sdkVersion&quot;:&quot;32.0.0&quot;,&quot;accountId&quot;:&quot;4c44c9d8-3cb6-4980-8505-ca0637cf3165&quot;,&quot;priority&quot;:&quot;high&quot;,&quot;credentials&quot;:{&quot;keystore&quot;:&quot;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&quot;,&quot;keyPassword&quot;:&quot;fb7409988d78459c826cf2a438cb3a33&quot;,&quot;keystoreAlias&quot;:&quot;QGRzb2thbC1sb2NhbC90dXJ0bGUtY2xpLWV4YW1wbGU=&quot;,&quot;keystorePassword&quot;:&quot;80c3583b33b84a1d91e5cf33b2421d7c&quot;},&quot;manifest&quot;:{&quot;android&quot;:{&quot;package&quot;:&quot;com.expo.turtle.cli.example&quot;},&quot;bundledAssets&quot;:[&quot;asset_3a2ba31570920eeb9b1d217cabe58315.ttf&quot;,&quot;asset_744ce60078c17d86006dd0edabcd59a7.ttf&quot;,&qLine truncated
@@ -1,2 +0,0 @@
recording.json filter=git-crypt diff=git-crypt
.gitatrributes !filter !diff
Binary file not shown.
-106
View File
@@ -1,106 +0,0 @@
import fs from 'fs-extra';
import nock from 'nock';
import config from 'turtle/config';
import { PLATFORMS } from 'turtle/constants';
import * as jobManager from 'turtle/jobManager';
import logger from 'turtle/logger';
jest.mock('../builders/utils/uploader.ts', () => ({
uploadBuildToS3: jest.fn(() => {
logger.debug('Faking uploading build');
return 'legit_path';
}),
}));
async function performSmokeTest(recording: string) {
jest.setTimeout(60 * 60 * 1000);
// @ts-ignore
const fixtureExists = await fs.exists(recording);
if (fixtureExists) {
logger.info('Fixture exists, test will use existing one.');
nock.load(recording);
mockLogs();
mockSQS();
logger.info('Loading fixture');
} else {
nock.recorder.rec({
dont_print: true,
output_objects: true,
enable_reqheaders_recording: false,
});
}
await jobManager.doJob();
if (!fixtureExists) {
await fs.writeFile(recording, JSON.stringify(nock.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('https://exp-shell-app-assets.s3.us-west-1.amazonaws.com')
.persist()
.put((uri: string) => {
return uri.indexOf('/logs') >= 0;
})
.reply(200);
}
function mockSQS() {
return nock('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('https://sqs.us-west-2.amazonaws.com:443')
.post('/', (body: any) => {
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: string) {
process.env.PLATFORM = platform;
const utils = require('turtle/aws/utils');
utils.QUEUE_URL = jest.fn((priority) => {
return (config.sqs.queues as any)[priority][platform];
});
nock.cleanAll();
nock.enableNetConnect();
const finishMock = mockFinish();
const fixtureLocation = `src/__smoke__/fixtures/${platform}/recording.json`;
await performSmokeTest(fixtureLocation);
expect(finishMock.isDone());
nock.disableNetConnect();
}
test('Android builds', async () => {
await testPlatform(PLATFORMS.ANDROID);
});
test('iOS builds', async () => {
await testPlatform(PLATFORMS.IOS);
});
-1
View File
@@ -1 +0,0 @@
declare module 'nock';
-90
View File
@@ -1,90 +0,0 @@
{
"id":"5980f894-d403-4909-a5e5-375eac188ff8",
"experienceId":"2c8d6f90-d05e-11e8-b439-fbdd43a1c21e",
"experienceName":"@admin/testApp",
"platform":"android",
"config":{
"releaseChannel":"default"
},
"status":"sent-to-queue",
"credentials":{
"keystore":"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",
"keyPassword":"9f47f3284e2a461eba7bc6cff302035d",
"keystoreAlias":"QGFkbWluL3Rlc3RBcHA=",
"keystorePassword":"aadb0c482eb340c0aee02b525460c576"
},
"manifest":{
"android":{
"package":"com.yourcompany.yourappname"
},
"bundledAssets":[
"asset_744ce60078c17d86006dd0edabcd59a7.ttf",
"asset_5221f35630f5b71e53c3196d3ff681a1.ttf",
"asset_517bb9a13989451be6623299153f503f.ttf",
"asset_b06871f281fee6b241d60582ae9369b9.ttf",
"asset_e20945d7c929279ef7a6f1db184a4470.ttf",
"asset_74c652671225d6ded874a648502e5f0a.ttf",
"asset_1eccbc4c41d49fd81840aef3eaabe862.ttf",
"asset_a37b0c01c0baf1888ca812cc0508f6e2.ttf",
"asset_9e9dbe78c20054a6d71d9c10c939ba68.ttf",
"asset_d2285965fe34b05465047401b8595dd0.ttf",
"asset_5cdf883b18a5651a29a4d1ef276d2457.ttf",
"asset_7d40544b395c5949f4646f5e150fe020.png",
"asset_cdd04e13d4ec83ff0cd13ec8dabdc341.png",
"asset_a132ecc4ba5c1517ff83c0fb321bc7fc.png",
"asset_0ea69b5077e7c4696db85dbcba75b0e1.png",
"asset_f5b790e2ac193b3d41015edb3551f9b8.png",
"asset_755fce460f64aed4d3f3ac1a6249ceea.png",
"asset_45a8ce76165dcaec1c5e39be15478e53.png",
"asset_2d8deea13c41b52b04442d91fb31c2c5.png",
"asset_5c36108361d0a750fd25533356f80245.png",
"asset_af47141a24eb8e5751dfd034159479bd.png",
"asset_ad107d1ca027259ca50ce0f432293e6c.png",
"asset_a30cd76fa74ee5a0bab5aba37c101416.png",
"asset_49a79d66bdea2debf1832bf4d7aca127.ttf",
"asset_778ffc9fe8773a878e9c30a6304784de.png",
"asset_376d6a4c7f622917c39feb23671ef71d.png",
"asset_c79c3606a1cf168006ad3979763c7e0c.png",
"asset_02bc1fa7c0313217bde2d65ccbff40c9.png",
"asset_35ba0eaec5a4f5ed12ca16fabeae451d.png"
],
"description":"A very interesting project.",
"icon":"./assets/images/icon.png",
"iconUrl":"https://d1wp6m56sqw74a.cloudfront.net/~assets/fa6577fecc0a7838f15a254577639984",
"ios":{
"bundleIdentifier":"com.niech.to.zadziala",
"supportsTablet":true
},
"locales":{
},
"name":"testApp",
"orientation":"portrait",
"platforms":[
"ios",
"android"
],
"privacy":"public",
"sdkVersion":"29.0.0",
"slug":"testApp",
"splash":{
"backgroundColor":"#ffffff",
"image":"./assets/images/splash.png",
"imageUrl":"https://d1wp6m56sqw74a.cloudfront.net/~assets/43ec0dcbe5a156bf9e650bb8c15e7af6",
"resizeMode":"contain"
},
"updates":{
"fallbackToCacheTimeout":0
},
"version":"1.0.0",
"id":"@admin/testApp",
"revisionId":"1.0.0-r.8wVOKbq7RP",
"publishedTime":"2018-10-15T09:39:12.773Z",
"commitTime":"2018-10-15T09:39:12.824Z",
"bundleUrl":"https://d1wp6m56sqw74a.cloudfront.net/%40admin%2FtestApp%2F1.0.0%2Ffa27a628bfe715851c97f32868948509-29.0.0-android.js",
"releaseChannel":"default",
"hostUri":"exp.host/@admin/testApp"
},
"sdkVersion":"29.0.0",
"messageCreatedTimestamp":1539596354060
}
-121
View File
@@ -1,121 +0,0 @@
{
"id": "2d46d6c6-aedd-429c-b5f7-a3a0b96fc916",
"experienceId": "a3987870-d11f-11e8-b439-fbdd43a1c21e",
"experienceName": "@admin/testApp",
"platform": "ios",
"config": {
"releaseChannel": "default",
"bundleIdentifier": "com.niech.to.zadziala"
},
"status": "sent-to-queue",
"credentials": {
"appId": "342LFMU86M",
"pushId": "4VU5PQBGHM",
"teamId": "QL76XYH73P",
"pushP12": "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\nHNZoKAQIbBakg4AhjA4=\n",
"features": {
"push": true,
"inAppPurchase": true,
"gameCenter": true,
"passbook": false,
"dataProtection": "",
"homeKit": false,
"cloudKitVersion": 2,
"iCloud": false,
"LPLF93JG7M": false,
"IAD53UNK2F": false,
"V66P55NK2I": false,
"SKC3T5S89Y": false,
"APG3427HIY": false,
"HK421J6T7P": false,
"WC421J6T7P": false
},
"teamName": "Alicja Warchał (Individual)",
"pushPassword": "ddCtxuuRHJZVPtf8lv/n1g==",
"enabledFeatures": [
"gameCenter",
"inAppPurchase",
"push"
],
"enterpriseAccount": "false",
"provisioningProfile": "MIIdwAYJKoZIhvcNAQcCoIIdsTCCHa0CAQExCzAJBgUrDgMCGgUAMIINVAYJ\nKoZIhvcNAQcBoIINRQSCDUE8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5n\nPSJVVEYtOCI/Pgo8IURPQ1RZUEUgcGxpc3QgUFVCTElDICItLy9BcHBsZS8v\nRFREIFBMSVNUIDEuMC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERz\nL1Byb3BlcnR5TGlzdC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+\nCjxkaWN0PgoJPGtleT5BcHBJRE5hbWU8L2tleT4KCTxzdHJpbmc+YWRtaW50\nZXN0QXBwIGM0YThkZjNmMTZkNzg1OWIxODc0YWFlZWUzY2ZhZWUwPC9zdHJp\nbmc+Cgk8a2V5PkFwcGxpY2F0aW9uSWRlbnRpZmllclByZWZpeDwva2V5PgoJ\nPGFycmF5PgoJPHN0cmluZz5RTDc2WFlINzNQPC9zdHJpbmc+Cgk8L2FycmF5\nPgoJPGtleT5DcmVhdGlvbkRhdGU8L2tleT4KCTxkYXRlPjIwMTgtMTAtMDhU\nMTQ6MzA6NTBaPC9kYXRlPgoJPGtleT5QbGF0Zm9ybTwva2V5PgoJPGFycmF5\nPgoJCTxzdHJpbmc+aU9TPC9zdHJpbmc+Cgk8L2FycmF5PgogICAgPGtleT5J\nc1hjb2RlTWFuYWdlZDwva2V5PgogICAgPGZhbHNlLz4KCTxrZXk+RGV2ZWxv\ncGVyQ2VydGlmaWNhdGVzPC9rZXk+Cgk8YXJyYXk+CgkJPGRhdGE+TUlJRm9U\nQ0NCSW1nQXdJQkFnSUlmTnFoZUpOZndFOHdEUVlKS29aSWh2Y05BUUVMQlFB\nd2daWXhDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFLREFwQmNIQnNaU0JK\nYm1NdU1Td3dLZ1lEVlFRTERDTkJjSEJzWlNCWGIzSnNaSGRwWkdVZ1JHVjJa\nV3h2Y0dWeUlGSmxiR0YwYVc5dWN6RkVNRUlHQTFVRUF3dzdRWEJ3YkdVZ1Yy\nOXliR1IzYVdSbElFUmxkbVZzYjNCbGNpQlNaV3hoZEdsdmJuTWdRMlZ5ZEds\nbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd0hoY05NVGd4TURBNE1UUXlNRE01\nV2hjTk1Ua3hNREE0TVRReU1ETTVXakNCbERFYU1CZ0dDZ21TSm9tVDhpeGtB\nUUVNQ2xGTU56WllXVWczTTFBeE9qQTRCZ05WQkFNTU1XbFFhRzl1WlNCRWFY\nTjBjbWxpZFhScGIyNDZJRUZzYVdOcVlTQlhZWEpqYUdIRmdpQW9VVXczTmxo\nWlNEY3pVQ2t4RXpBUkJnTlZCQXNNQ2xGTU56WllXVWczTTFBeEdEQVdCZ05W\nQkFvTUQwRnNhV05xWVNCWFlYSmphR0hGZ2pFTE1Ba0dBMVVFQmhNQ1ZWTXdn\nZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEa3Uy\nVHY4VmRCaERPY1E2ckQ3NFlON1UwNDZzRjQ5VTVHc2tPSUNidVY4cFE0YktP\nUTR4YmpNMXEreFhhMTJsRXUzdzBYc09KMHltemQ2OUdsdjhFVnNiT1JUcHkr\nTHVuLzVVRGpITXdpc1RNYjM1U3RWRi9XekV0TStWUFA2VGg0TGhmOHRYTGNi\nbVpxdi91M2d5eHBUc3NKb1VkenRyUko2bGczUStSbXM0RWFEekY0V2lnZDdo\nNVBmRFR5bEpJOFlEWlF3WEpxeTc4NG1pRmQ2eTVaM1dRZHhaaldMOHBGc0RT\nK1ZpZndLWUU0QU5tZHorZ2pEUEkrREJ0dHBrdDdZYWxVVmFLYkdBTW8zbjdV\nUkY4eEhkZm1yUk93MkJzd21WTnBDNkdMdFQzVVRpQVNKSjMxS0JVUmI1aWVI\nTTRKQTVLc2wxbk9yWkxSTXhtNjRxR0hBZ01CQUFHamdnSHhNSUlCN1RBTUJn\nTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRklnbkZ3bXB0aGhnaSt6\ncnV2WkhXY1ZTVktPM01EOEdDQ3NHQVFVRkJ3RUJCRE13TVRBdkJnZ3JCZ0VG\nQlFjd0FZWWphSFIwY0RvdkwyOWpjM0F1WVhCd2JHVXVZMjl0TDI5amMzQXdN\neTEzZDJSeU1URXdnZ0VkQmdOVkhTQUVnZ0VVTUlJQkVEQ0NBUXdHQ1NxR1NJ\nYjNZMlFGQVRDQi9qQ0J3d1lJS3dZQkJRVUhBZ0l3Z2JZTWdiTlNaV3hwWVc1\nalpTQnZiaUIwYUdseklHTmxjblJwWm1sallYUmxJR0o1SUdGdWVTQndZWEow\nZVNCaGMzTjFiV1Z6SUdGalkyVndkR0Z1WTJVZ2IyWWdkR2hsSUhSb1pXNGdZ\nWEJ3YkdsallXSnNaU0J6ZEdGdVpHRnlaQ0IwWlhKdGN5QmhibVFnWTI5dVpH\nbDBhVzl1Y3lCdlppQjFjMlVzSUdObGNuUnBabWxqWVhSbElIQnZiR2xqZVNC\naGJtUWdZMlZ5ZEdsbWFXTmhkR2x2YmlCd2NtRmpkR2xqWlNCemRHRjBaVzFs\nYm5SekxqQTJCZ2dyQmdFRkJRY0NBUllxYUhSMGNEb3ZMM2QzZHk1aGNIQnNa\nUzVqYjIwdlkyVnlkR2xtYVdOaGRHVmhkWFJvYjNKcGRIa3ZNQllHQTFVZEpR\nRUIvd1FNTUFvR0NDc0dBUVVGQndNRE1CMEdBMVVkRGdRV0JCVFFBUi9uZXVa\nV1dzOEUvYXc3QWhoR1ZOZWdzVEFPQmdOVkhROEJBZjhFQkFNQ0I0QXdFd1lL\nS29aSWh2ZGpaQVlCQkFFQi93UUNCUUF3RFFZSktvWklodmNOQVFFTEJRQURn\nZ0VCQUhka2FJMzN2aVBGc2xIWXBXTi8wdVorZVpxWWpPMkE3QStCeGxqMnFh\nTEY5STI0dngwMzUyd1g1KzBXWUh2eGlTTzY2VXdSV04rek85eFZ4dnlqeEdI\naGdQbGJzMVlldmszdDBWYUc5WXM5TUw5RHVVNllxWEU2YWo1ZnNuVG5yOEcx\nUnZHYkFqM2d4ZXRKRzlxTDU3ODdBUGNuSnp6NzlVdVBkQVhlVThZNW0xSzZU\nT0FzM2IzdFJ1SE02U0JwM1lDMVhqNGZLVUxLdXRHV2lVdXFDQnFsUFgydmt6\nQUkxZnp1U0NPZ2pORGdKSFZBQnBEWlpzaUxETHczWjJ2RGh5YWtOdXB5UENZ\nRE92T2xZblkrU000d1Z4OTVncUtDVW5ZWDgwSSs4U3F6ZWg4QU9Ib3d2d0ZU\nMHIxSWowTkJSMnhKN0NlK3BETzlveUtGd2VFYVQwOD08L2RhdGE+Cgk8L2Fy\ncmF5PgoKCgk8a2V5PkVudGl0bGVtZW50czwva2V5PgoJPGRpY3Q+CgkJPGtl\neT5rZXljaGFpbi1hY2Nlc3MtZ3JvdXBzPC9rZXk+CgkJPGFycmF5PgoJCQk8\nc3RyaW5nPlFMNzZYWUg3M1AuKjwvc3RyaW5nPgkJCgkJPC9hcnJheT4KCQk8\na2V5PmdldC10YXNrLWFsbG93PC9rZXk+CgkJPGZhbHNlLz4KCQk8a2V5PmFw\ncGxpY2F0aW9uLWlkZW50aWZpZXI8L2tleT4KCQk8c3RyaW5nPlFMNzZYWUg3\nM1AuY29tLm5pZWNoLnRvLnphZHppYWxhPC9zdHJpbmc+CgkJPGtleT5jb20u\nYXBwbGUuZGV2ZWxvcGVyLnRlYW0taWRlbnRpZmllcjwva2V5PgoJCTxzdHJp\nbmc+UUw3NlhZSDczUDwvc3RyaW5nPgoJCTxrZXk+YXBzLWVudmlyb25tZW50\nPC9rZXk+CgkJPHN0cmluZz5wcm9kdWN0aW9uPC9zdHJpbmc+CgkJPGtleT5i\nZXRhLXJlcG9ydHMtYWN0aXZlPC9rZXk+CgkJPHRydWUvPgoKCTwvZGljdD4K\nCTxrZXk+RXhwaXJhdGlvbkRhdGU8L2tleT4KCTxkYXRlPjIwMTktMTAtMDhU\nMTQ6MjA6MzlaPC9kYXRlPgoJPGtleT5OYW1lPC9rZXk+Cgk8c3RyaW5nPmNv\nbS5uaWVjaC50by56YWR6aWFsYSBBcHBTdG9yZTwvc3RyaW5nPgoJPGtleT5U\nZWFtSWRlbnRpZmllcjwva2V5PgoJPGFycmF5PgoJCTxzdHJpbmc+UUw3NlhZ\nSDczUDwvc3RyaW5nPgoJPC9hcnJheT4KCTxrZXk+VGVhbU5hbWU8L2tleT4K\nCTxzdHJpbmc+QWxpY2phIFdhcmNoYSYjMzIyOzwvc3RyaW5nPgoJPGtleT5U\naW1lVG9MaXZlPC9rZXk+Cgk8aW50ZWdlcj4zNjQ8L2ludGVnZXI+Cgk8a2V5\nPlVVSUQ8L2tleT4KCTxzdHJpbmc+NjYyMmQ5ODgtYjQyOS00Nzk1LTlkY2It\nM2I5ZjY5YmYzNGE2PC9zdHJpbmc+Cgk8a2V5PlZlcnNpb248L2tleT4KCTxp\nbnRlZ2VyPjE8L2ludGVnZXI+CjwvZGljdD4KPC9wbGlzdD6ggg2xMIID8zCC\nAtugAwIBAgIBFzANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzETMBEG\nA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv\nbiBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDcwNDEy\nMTc0MzI4Line truncated
"provisioningProfileId": "WX8B857VDM",
"pushPrivateSigningKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAokW6QiqVOm0gXmyY2aBVRNxeVeSg5u1j0wYSbMc64F90UUlJ\nwVcqDxQdAqo7z1RHTsUAazLriY5cqle+ivxjNTqKmvpmUd85ajMTSG6GaQPG4RHw\nAkRY+d221HUV9L81R0RY9VrOEhzqtoUmDGiv5AWz88xcVnU/3R59LSGqiV9nerP9\nDRkUHoAlW7Ga6YUKXtqdhSOspSZq/plar3oogGQD4WFKr2j1B1R2t8xuZoe2H956\nHxTzb4Y2jRZNuqME4R5dgsHIxvhQbAVYQCVPYrsGa+74WsXFBa6/kVSrRuLbYYIa\nfrqw1hTy0ujzQzcmOBOpBAiJb4ZfCM60rHaYcwIDAQABAoIBABbFCfm21/G21k/p\nlRkUcmKTOXl790fwD43Q0E0LN6u8OSoeyoaioHg1Lkztbi8NeGQJKKHiJ0LKAx6z\n6Ty/ZXxWlpRghnL+i6PnPtFvENUzfnied7sZtBJ7legB9e691dAGOyVSdI/+FsE9\ntbUQC35HfpS7HEnVcfypBo+Kpc9YpnfsKPXfk4lZTHnuE9G0pDE9Nhz3MSHdG3uz\nTOuQa+aKKcek38Y7dPJuioG/ffqlhoCFBLTwR/owil8cWx3THX7yvYzTPCAbosiY\nZdzM/JYgpi0kSoV30pnT6EfBl/qMtgo6jV6wrZ5FL8lR6iW/RsTbb4CMznLXyuMF\newsTuaECgYEA1y59P0LEfsyuqF/7nXohyPu4ddmQsxLrb4hQFxznFwEKHvNW8P9c\n+soCp0DBNZHENZG3r3GHMmcKnmdgqFjFQESqEwzTHjLSD5bipFOXXkf8ILownVpp\nkYnJVBWEFGsinZOinkMKg1t0Cp0lAmKsEGC1PLrk1vRuoW8RWenFcfUCgYEAwQ3k\n+95b5LA44lXyZ+T2ojY4HAdnYKeMO3eoAgRzdYVrCJ+vgK+fbnBx2pedUw0Ct/O3\n9imSvUoqoBAkfcqWTGdxmsITYuLFaD64g+XLQjGmZCQlQTrd0FWFYAYQEVeq2GQu\nx5WarZBgJ2N76ReDDbV0y34igAw7/lRbTn8GF8cCgYEArdPiXc5ECeKzXVVcX9Sf\nokqmsp005VRtWMYXXPR+QfkXAfW10C2aIQY7qn0HF41Poa67YkEl5DOVQm1kidpc\nThSqB4WerpCDXRCYugLFDua76HxAdXzqNyXFu+U9s3jwl7cB8TNbNM4WKdTUZt7q\n/LgC8LJR1svS6xpcO/Q7ClkCgYEAipi5DgGjI1lIXWWqs9/zGJ2oRqciFofy6zaK\nTXh4k6SHJRfPXam34gekFXTHo7oxe3LjXTyXdoHqfCNar1xj7tJNAvfWByYa5y4w\nNbEh7ZHLjRVOEbh7Sng7Wqa/nlO7+cJiuzKya2y9O0n2yW7xzUO6Z+VUS219HKff\nLUmQTD0CgYEAydaBypz1wWD5qpQCP8u3kfkmmfRMi9fL+kdfb2ldUUo3JVl1ikpW\ntjhELvzjHVuI39lDI4gHRjoUPMvLwUxhF0zB6CCl6D6g67TfWKecLy/RgttnwLf5\nlAFa1fzYVS+Z54nreohgbq4qsFzq3p6NbPQIejBskaqtfQIVb2vSGs8=\n-----END RSA PRIVATE KEY-----\n",
"certId": "XLKCSBMJDV",
"certP12": "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\n1eOAa/1MCq2acE8AkzAUz+XABAiLGr17TUyqog==\n",
"certPassword": "AcovcuslT2sK2PNKxeK2Vw==",
"certPrivateSigningKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA5Ltk7/FXQYQznEOqw++GDe1NOOrBePVORrJDiAm7lfKUOGyj\nkOMW4zNavsV2tdpRLt8NF7DidMps3evRpb/BFbGzkU6cvi7p/+VA4xzMIrEzG9+U\nrVRf1sxLTPlTz+k4eC4X/LVy3G5mar/7t4MsaU7LCaFHc7a0SepYN0PkZrOBGg8x\neFooHe4eT3w08pSSPGA2UMFyasu/OJohXesuWd1kHcWY1i/KRbA0vlYn8CmBOADZ\nnc/oIwzyPgwbbaZLe2GpVFWimxgDKN5+1ERfMR3X5q0TsNgbMJlTaQuhi7U91E4g\nEiSd9SgVEW+YnhzOCQOSrJdZzq2S0TMZuuKhhwIDAQABAoIBADmfM9h2liK9KTtO\nmLBvoPfVNkUGbuMH+UY6FmUo/obR66EjTTls3BE0mMHCgRti+lyyeFvlhcciT7bA\nd7onyn6qm7AZe8c1jmGW4XfVg1+iAFwfQRdBUDuOj9G+ZezUthMgmY5iL6N0dHyk\nDMe4VfHZlbDBXny6JEUSslKJ2fo8+HcgR8/+UQD9LA1fITVsbn6/T0lQd8ZyoX4J\nJ6VVhwkWIQUuJ+Ff2O/ttQGFrqWPxcQc0H07MAW7QM3Tc5laGRcOBGCLFw+XhIla\nVsfuO4JF2Uzxpq3YkmpFdW60ZL00groySmjKqZfF8wJqnOyBltmlZDPJrwzxfkYn\nKmy+hCECgYEA8liKuG2PA8Gme7IDUvUlk+GKDTwnN4PMrwLvcRm+T/wzHjpuWelr\nmTeXPOAd6xg16YD2pxOCg7Rd1CC+LifMfnwZ+oKnobRYrZzyMwn8RfLEu7luBbSs\nSsXmkVgxt7H4Ctn3bthcYUNJBFw9MFSYZBiESbvXlWJihbVh2RRG9U8CgYEA8Z5+\ncSk2vItyEuY85cPJ66rpS0bIa5tyLdC22ZjZeRKhVwxR3Ubj2XtnMh6esnNvzdzl\nWK8GYzVqwo1Agf3YxUHoFU2sBmE739gqsGsXc0MaUYEWL/NQP6RZwndosvdlz0vC\nUucmoVIFmbYCUZm0fdxWAs4caqp+axwqzgie8kkCgYA972z8d1t+fUY8BKGe2PIS\nmih6+22WXYO5Eon5ILgnnu+9gPdk2Sfbj36CW1CqHZThqUjgKDdJy5XTOc8A4sD7\nbmIBSNTombu0GxE3BA1KHyIyS9CXerYxoeQsLxr9tGkM9OmslXT+koCdsakdqfEM\nW8urQGt3TR6ax2FLZkhANwKBgQDWSvjfymrWjGKvKm6GZcCXeO0Sq4OkFKkOw1b4\n5Jy0yfY4ax/MPkxlHhKnnAqqQMG/dpQetJTYto6qYHb/E7IHOW3qPwo8Wk6tOF6c\nO08AFlqoQPH5szXQTCaj2B4O5GbylMGTn5leaI25B3lFACrZmera8Ay5+d7HhqLc\nOz8lqQKBgQDGVYe+CxAQ+LaM9VG8endl9br0Heop0/yDVm01I1oVy+lcF5ySuZmj\nvvKJtS7Dfc9NHKz+tht88uznaD6E3Nh3fT6J9w1lKsdgLToDcCs1B9pWiMaQWhJR\n2uz9a4pCn5E96rihIHzS1+SjnEGNgIVEieT6uSlnEf1MXJ0e/oGFXQ==\n-----END RSA PRIVATE KEY-----\n"
},
"manifest": {
"android": {
"package": "com.yourcompany.yourappname"
},
"bundledAssets": [
"asset_744ce60078c17d86006dd0edabcd59a7.ttf",
"asset_5221f35630f5b71e53c3196d3ff681a1.ttf",
"asset_517bb9a13989451be6623299153f503f.ttf",
"asset_b06871f281fee6b241d60582ae9369b9.ttf",
"asset_e20945d7c929279ef7a6f1db184a4470.ttf",
"asset_74c652671225d6ded874a648502e5f0a.ttf",
"asset_1eccbc4c41d49fd81840aef3eaabe862.ttf",
"asset_a37b0c01c0baf1888ca812cc0508f6e2.ttf",
"asset_9e9dbe78c20054a6d71d9c10c939ba68.ttf",
"asset_d2285965fe34b05465047401b8595dd0.ttf",
"asset_5cdf883b18a5651a29a4d1ef276d2457.ttf",
"asset_7d40544b395c5949f4646f5e150fe020.png",
"asset_cdd04e13d4ec83ff0cd13ec8dabdc341.png",
"asset_a132ecc4ba5c1517ff83c0fb321bc7fc.png",
"asset_0ea69b5077e7c4696db85dbcba75b0e1.png",
"asset_f5b790e2ac193b3d41015edb3551f9b8.png",
"asset_755fce460f64aed4d3f3ac1a6249ceea.png",
"asset_45a8ce76165dcaec1c5e39be15478e53.png",
"asset_2d8deea13c41b52b04442d91fb31c2c5.png",
"asset_5c36108361d0a750fd25533356f80245.png",
"asset_af47141a24eb8e5751dfd034159479bd.png",
"asset_ad107d1ca027259ca50ce0f432293e6c.png",
"asset_a30cd76fa74ee5a0bab5aba37c101416.png",
"asset_49a79d66bdea2debf1832bf4d7aca127.ttf",
"asset_778ffc9fe8773a878e9c30a6304784de.png",
"asset_376d6a4c7f622917c39feb23671ef71d.png",
"asset_c79c3606a1cf168006ad3979763c7e0c.png",
"asset_02bc1fa7c0313217bde2d65ccbff40c9.png",
"asset_35ba0eaec5a4f5ed12ca16fabeae451d.png"
],
"description": "A very interesting project.",
"icon": "./assets/images/icon.png",
"iconUrl": "https://d1wp6m56sqw74a.cloudfront.net/~assets/fa6577fecc0a7838f15a254577639984",
"ios": {
"bundleIdentifier": "com.niech.to.zadziala",
"supportsTablet": true
},
"locales": {},
"name": "testApp",
"orientation": "portrait",
"platforms": [
"ios",
"android"
],
"privacy": "public",
"sdkVersion": "29.0.0",
"slug": "testApp",
"splash": {
"backgroundColor": "#ffffff",
"image": "./assets/images/splash.png",
"imageUrl": "https://d1wp6m56sqw74a.cloudfront.net/~assets/43ec0dcbe5a156bf9e650bb8c15e7af6",
"resizeMode": "contain"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"version": "1.0.0",
"id": "@admin/testApp",
"revisionId": "1.0.0-r.zV1W89wn23",
"publishedTime": "2018-10-16T08:44:05.362Z",
"commitTime": "2018-10-16T08:44:05.403Z",
"bundleUrl": "https://d1wp6m56sqw74a.cloudfront.net/%40admin%2FtestApp%2F1.0.0%2Fb8678e2be7cd5bb9e240db0dd3c691c0-29.0.0-ios.js",
"releaseChannel": "default",
"hostUri": "exp.host/@admin/testApp"
},
"sdkVersion": "29.0.0",
"messageCreatedTimestamp": 1539679447643
}
-5
View File
@@ -1,5 +0,0 @@
import * as context from 'turtle/turtleContext';
test('Initially should not exit', () => {
expect(context.checkShouldExit()).toBe(false);
});
-14
View File
@@ -1,14 +0,0 @@
import * as validator from 'turtle/validator';
const testValidator = (fixturePath: string) => {
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');
});
-2
View File
@@ -1,2 +0,0 @@
export const EXTRA_DIMENSIONS = Symbol('Extra Dimensions');
export const GROUP_HASH = Symbol('Group Hash');
-40
View File
@@ -1,40 +0,0 @@
import config from 'turtle/config';
export const TYPE_DIMENSIONS = (type: string) => [
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'type', Value: type },
],
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'type', Value: type },
{ Name: 'host', Value: config.hostname },
],
];
export const PRIORITY_DIMENSIONS = (type: string, priority: string) => [
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'priority', Value: priority },
],
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'type', Value: type },
],
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'type', Value: type },
{ Name: 'priority', Value: priority },
],
[
{ Name: 'env', Value: config.deploymentEnv },
{ Name: 'platform', Value: config.platform },
{ Name: 'type', Value: type },
{ Name: 'host', Value: config.hostname },
],
];
-186
View File
@@ -1,186 +0,0 @@
import aws from 'aws-sdk';
import _ from 'lodash';
import { EXTRA_DIMENSIONS, GROUP_HASH } from 'turtle/aws/cloudwatch/constants';
import calculateStatistics from 'turtle/aws/cloudwatch/statistics';
import {
IMetric,
IMetricConfiguration,
IMetricData,
IMetricsChunk,
MetricRegistrationObject,
} from 'turtle/aws/cloudwatch/types';
import config from 'turtle/config';
import logger from 'turtle/logger';
interface IState {
metrics: IMetric[];
registeredMetrics: {
[key: string]: IMetricConfiguration;
};
intervalId: NodeJS.Timer | null;
}
const SUCCESS_SUFFIX = '.success';
const FAIL_SUFFIX = '.fail';
const CHUNK_SIZE = 20;
const state: IState = {
metrics: [],
registeredMetrics: {},
intervalId: null,
};
const cloudWatch = new aws.CloudWatch({
apiVersion: '2010-08-01',
region: config.cloudwatch.region,
accessKeyId: config.aws.accessKeyId,
secretAccessKey: config.aws.secretAccessKey,
});
export function init() {
if (config.cloudwatch.disabled) {
return;
}
state.intervalId = setInterval(_dumpMetrics, config.cloudwatch.intervalMs);
}
export function addMetricData({
name,
value,
success = true,
explicitName = false,
extraDimensions = [],
}: IMetricData) {
if (config.cloudwatch.disabled) {
return;
}
const metricName = explicitName ? name : _createMetricName(name, success);
const registeredMetric = state.registeredMetrics[metricName];
if (!registeredMetric) {
return;
}
const { unit } = registeredMetric;
const metric: IMetric = {
MetricName: metricName,
Unit: unit,
Value: value,
Timestamp: new Date(),
[EXTRA_DIMENSIONS]: extraDimensions,
[GROUP_HASH]: _calculateGroupHash(metricName, extraDimensions),
};
state.metrics.push(metric);
}
export function registerMetric({
metricName,
unit,
reducer,
dimensions = [],
statistics = false,
addEmpty = true,
explicitName = false,
}: MetricRegistrationObject) {
if (config.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 };
}
}
function _createMetricName(name: string, success: boolean, explicitName?: boolean) {
if (explicitName) {
return name;
} else {
const suffix = success ? SUCCESS_SUFFIX : FAIL_SUFFIX;
return `${name}${suffix}`;
}
}
function _calculateGroupHash(metricName: string, extraDimensions: any[]) {
const dimString = _.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.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: IMetric[]) {
const seenMetrics = metrics.reduce((acc, i) => {
if (!acc.has(i.MetricName)) {
acc.add(i.MetricName);
}
return acc;
}, new Set());
const nonEmptyMetrics = _.omitBy(state.registeredMetrics, ({ addEmpty }) => !addEmpty);
const toAdd = _.difference(Object.keys(nonEmptyMetrics), Array.from(seenMetrics));
toAdd.forEach((name) => addMetricData({ name, value: 0, explicitName: true }));
}
function _formatMetrics(metrics: IMetric[]) {
const reducedMetrics = _reduceMetrics(metrics);
const metricsWithDimensions = reducedMetrics.map((metric) => {
const { dimensions } = state.registeredMetrics[metric.MetricName];
const joinedDimensions = [...dimensions, ...metric[EXTRA_DIMENSIONS]];
return joinedDimensions.map((i) => Object.assign({}, metric, { Dimensions: i }));
});
const metricData = _.flatten(metricsWithDimensions);
const chunks = _.chunk(metricData, CHUNK_SIZE);
return chunks.map((chunk) => ({
Namespace: config.cloudwatch.namespace,
MetricData: chunk,
}));
}
function _reduceMetrics(metrics: IMetric[]) {
const grouped = _.groupBy(metrics, GROUP_HASH);
return _.reduce(
grouped,
(acc: IMetric[], val: any) => {
const { MetricName: key } = val[0] as IMetric;
const { reducer, statistics } = state.registeredMetrics[key];
const reduced = reducer ? reducer(val) : val;
const withStats = statistics ? calculateStatistics(reduced) : reduced;
acc.push(...withStats);
return acc;
},
[],
);
}
function _pushMetrics(metrics: IMetricsChunk[]) {
logger.trace('[cloudwatch] pushing metrics', JSON.stringify(metrics, null, '\t'));
metrics.forEach((metricsChunk) => {
cloudWatch.putMetricData(metricsChunk, (err) => {
if (err) {
logger.warn({ err }, '[cloudwatch]');
}
});
});
}
-27
View File
@@ -1,27 +0,0 @@
import { IMetric } from 'turtle/aws/cloudwatch/types';
export function sum(metrics: IMetric[]) {
if (metrics.length === 0) {
return [];
}
const reduced = metrics.reduce((acc: IMetric | null, i: IMetric) => {
let result = acc;
if (!result) {
result = { ...i };
} else {
result.Value += i.Value;
}
return result;
}, null);
return [reduced];
}
export function avg(metrics: IMetric[]) {
if (!metrics.length) {
return [];
}
const metric = sum(metrics)[0] as IMetric;
metric.Value = metric.Value / metrics.length;
return [metric];
}
-29
View File
@@ -1,29 +0,0 @@
import { IMetric, MetricWithStats } from 'turtle/aws/cloudwatch/types';
export default function calculateStatistics(metrics: IMetric[]) {
if (!metrics.length) {
return [];
}
const reduced = metrics.reduce((acc: MetricWithStats | null, i: IMetric) => {
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];
}
-48
View File
@@ -1,48 +0,0 @@
import { EXTRA_DIMENSIONS, GROUP_HASH } from 'turtle/aws/cloudwatch/constants';
export interface IMetric {
MetricName: string;
Unit: string;
Value: number;
Timestamp: Date;
StatisticValues?: {
Maximum: number;
Minimum: number;
SampleCount: number;
Sum: number;
};
[EXTRA_DIMENSIONS]: any;
[GROUP_HASH]: string;
}
export type MetricWithStats = {
StatisticValues: {
Maximum: number;
Minimum: number;
SampleCount: number;
Sum: number;
},
} & IMetric;
export interface IMetricData {
name: string;
value: number;
success?: boolean;
explicitName?: boolean;
extraDimensions?: any;
}
export interface IMetricConfiguration {
unit: string;
statistics?: boolean;
reducer?: any;
addEmpty?: boolean;
dimensions?: any;
}
export type MetricRegistrationObject = { metricName: string, explicitName?: boolean } & IMetricConfiguration;
export interface IMetricsChunk {
Namespace: string;
MetricData: IMetric[];
}
-28
View File
@@ -1,28 +0,0 @@
import AWS from 'aws-sdk';
import fs from 'fs-extra';
import _ from 'lodash';
import config from 'turtle/config';
interface IFileUploadParams {
bucketName?: string;
key: string;
srcPath: string;
}
const s3 = new AWS.S3({
..._.pick(config.aws, ['accessKeyId', 'secretAccessKey']),
..._.pick(config.s3, ['region']),
});
export default s3;
export async function uploadFile({ bucketName = config.s3.bucket, key, srcPath }: IFileUploadParams) {
return await s3
.upload({
Bucket: bucketName,
Key: key,
Body: fs.createReadStream(srcPath),
})
.promise();
}
-91
View File
@@ -1,91 +0,0 @@
import retry from 'async-retry';
import AWS from 'aws-sdk';
import _ from 'lodash';
import { OUTPUT_QUEUE_URL, QUEUE_URL } from 'turtle/aws/utils';
import config from 'turtle/config';
import { JOB_UPDATE_TYPE } from 'turtle/constants/build';
import logger from 'turtle/logger';
import { getCurrentJobId } from 'turtle/turtleContext';
const sqs = new AWS.SQS({
apiVersion: '2012-11-05',
..._.pick(config.aws, ['accessKeyId', 'secretAccessKey']),
..._.pick(config.sqs, ['region']),
});
const VISIBILITY_TIMEOUT_SEC = 30;
export async function receiveMessage(priority: string) {
const params = {
MaxNumberOfMessages: 1,
QueueUrl: QUEUE_URL(priority),
VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,
};
return await retry(() => {
return sqs
.receiveMessage(params)
.promise()
.then((data) => {
if (data.Messages) {
logger.info(`Received a message`);
return data.Messages[0];
} else {
logger.debug(`No messages received [${priority}]`);
return null;
}
})
.catch((err) => {
logger.error({ err }, 'Receive error');
throw err;
});
});
}
export async function deleteMessage(priority: string, receiptHandle: string) {
const params = {
QueueUrl: QUEUE_URL(priority),
ReceiptHandle: receiptHandle,
};
return await retry(() => {
return sqs.deleteMessage(params).promise();
});
}
export async function changeMessageVisibility(priority: string, receiptHandle: string) {
const params = {
QueueUrl: QUEUE_URL(priority),
ReceiptHandle: receiptHandle,
VisibilityTimeout: VISIBILITY_TIMEOUT_SEC,
};
return sqs.changeMessageVisibility(params).promise();
}
// 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
export function changeMessageVisibilityRecurring(priority: string, receiptHandle: string, jobId: string) {
return setInterval(() => {
if (getCurrentJobId() === jobId) {
changeMessageVisibility(priority, receiptHandle).catch((err) => {
logger.warn({ err }, 'Error at change msg visibility');
});
}
}, (VISIBILITY_TIMEOUT_SEC * 1000) / 3);
}
export async function sendMessage(jobId: string, status: JOB_UPDATE_TYPE, data = {}) {
const params = {
MessageBody: JSON.stringify({ jobId, status, ...data }),
QueueUrl: OUTPUT_QUEUE_URL(),
DelaySeconds: 0,
MessageGroupId: jobId,
};
try {
return await retry(async () => {
return await sqs.sendMessage(params).promise();
});
} catch (err) {
logger.error({ err }, `Error sending SQS message: ${JSON.stringify(params)}}`);
}
}
-4
View File
@@ -1,4 +0,0 @@
import config from 'turtle/config';
export const QUEUE_URL = (priority: string) => (config.sqs.queues as any)[priority][config.platform];
export const OUTPUT_QUEUE_URL = () => config.sqs.queues.out;
-2
View File
@@ -1,2 +0,0 @@
export class ErrorWithCommandHelp extends Error {
}
-2
View File
@@ -1,2 +0,0 @@
export class ErrorWithProgramHelp extends Error {
}
-87
View File
@@ -1,87 +0,0 @@
import fs from 'fs-extra';
import _ from 'lodash';
import uuid from 'uuid';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { createBuilderAction } from 'turtle/bin/utils/builder';
import builder from 'turtle/builders/android';
import { PLATFORMS } from 'turtle/constants';
export default (program: any, setCommonCommandOptions: any) => {
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',
)
.description(
'Build a standalone APK or App Bundle for your project, signed and ready for submission to the Google Play'
+ ' Store.',
)
.asyncAction(
createBuilderAction({
program,
command,
prepareCredentials,
buildJobObject,
builder,
platform: PLATFORMS.ANDROID,
os: ['darwin', 'linux'],
}),
);
};
const buildJobObject = (
appJSON: any,
{ releaseChannel, username, projectDir, publicUrl, buildType }: any,
credentials: any,
) => ({
config: {
..._.get(appJSON, 'expo.android.config', {}),
releaseChannel,
androidPackage: _.get(appJSON, 'expo.android.package'),
publicUrl,
buildType,
},
id: uuid.v4(),
platform: PLATFORMS.ANDROID,
sdkVersion: _.get(appJSON, 'expo.sdkVersion'),
projectDir,
experienceName: `@${username}/${_.get(appJSON, 'expo.slug')}`,
...(credentials && { credentials }),
});
const prepareCredentials = async (cmd: any) => {
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(
'Please provide all required credentials - Keystore (with password), Keystore alias and Key password',
);
} else {
return null;
}
} else {
return {
keystore: (await fs.readFile(keystorePath)).toString('base64'),
keystoreAlias,
keystorePassword,
keyPassword,
};
}
};
-30
View File
@@ -1,30 +0,0 @@
import { default as buildAndroid } from 'turtle/bin/commands/build/android';
import { default as buildIOS } from 'turtle/bin/commands/build/ios';
function createCommand(builder: any) {
return (program: any) => {
return builder(program, setCommonCommandOptions);
};
}
function setCommonCommandOptions(cmd: any) {
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).',
)
.option(
'--release-channel <channel-name>',
'pull from specified release channel (default: default)',
)
.option('-c --config <config-file>', 'specify a path to app.json');
}
export default {
ios: createCommand(buildIOS),
android: createCommand(buildAndroid),
};
-82
View File
@@ -1,82 +0,0 @@
import fs from 'fs-extra';
import _ from 'lodash';
import uuid from 'uuid';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { createBuilderAction } from 'turtle/bin/utils/builder';
import builder from 'turtle/builders/ios';
import { IOS_BUILD_TYPES, PLATFORMS } from 'turtle/constants';
export default (program: any, setCommonCommandOptions: any) => {
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(
createBuilderAction({
program,
command,
prepareCredentials,
buildJobObject,
builder,
platform: PLATFORMS.IOS,
os: 'darwin',
}),
);
};
const buildJobObject = (appJSON: any, { releaseChannel, buildType, username, publicUrl }: any, credentials: any) => ({
config: {
..._.get(appJSON, 'expo.ios.config', {}),
buildType,
releaseChannel,
bundleIdentifier: _.get(appJSON, 'expo.ios.bundleIdentifier'),
publicUrl,
},
id: uuid.v4(),
platform: PLATFORMS.IOS,
sdkVersion: _.get(appJSON, 'expo.sdkVersion'),
experienceName: `@${username}/${_.get(appJSON, 'expo.slug')}`,
...(credentials && { credentials }),
});
const prepareCredentials = async (cmd: any) => {
if (cmd.type !== 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(
'Please provide all required credentials'
+ '- Apple Team ID, Distribution Certificate P12 (with password) and Provisioning Profile',
);
}
return {
teamId,
certP12: (await fs.readFile(distP12Path)).toString('base64'),
certPassword,
provisioningProfile: (await fs.readFile(provisioningProfilePath)).toString('base64'),
};
};
-8
View File
@@ -1,8 +0,0 @@
import builders from 'turtle/bin/commands/build';
import setup from 'turtle/bin/commands/setup';
export const setupIOS = setup.ios;
export const setupAndroid = setup.android;
export const buildIOS = builders.ios;
export const buildAndroid = builders.android;
-49
View File
@@ -1,49 +0,0 @@
import _ from 'lodash';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';
import setup from 'turtle/bin/setup/setup';
import { PLATFORMS } from 'turtle/constants';
import logger from 'turtle/logger';
const l = logger.child({ buildPhase: 'setting up environment' });
function createSetupCommand(platform: string, os?: string) {
return (program: any) => {
const command = program.command(`setup:${platform}`);
const platformFirstLetter = platform[0];
command
.alias(`s${platformFirstLetter}`)
.description(`Setup environment for building ${_.capitalize(platform)} standalone apps.`)
.option(
'--sdk-version <sdk-version>',
'version of Expo SDK shell app to download (optional)',
)
.asyncAction(async (cmd: any) => await setupAction(program, cmd, platform, os));
};
}
async function setupAction(program: any, cmd: any, platform: string, os?: string) {
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(platform, sdkVersion);
l.info('it\'s all set!');
} catch (err) {
logger.error({ err }, `Failed to setup environment for ${platform} builds`);
if (err instanceof ErrorWithCommandHelp) {
cmd.help();
} else if (err instanceof ErrorWithProgramHelp) {
program.help();
}
process.exit(1);
}
}
export default {
ios: createSetupCommand(PLATFORMS.IOS, 'darwin'),
android: createSetupCommand(PLATFORMS.ANDROID),
};
-51
View File
@@ -1,51 +0,0 @@
import os from 'os';
import path from 'path';
import _ from 'lodash';
import { env } from 'turtle/utils/env';
const resolveEnv = () => {
if (env('EXPO_LOCAL', '0') === '1') {
return 'local';
} else if (env('EXPO_STAGING', '0') === '1') {
return 'staging';
} else {
return 'production';
}
};
const currentEnv = resolveEnv();
const isLocal = (envName: string) => envName === 'local';
const isStaging = (envName: string) => 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.join(os.homedir(), 'expo-apps'),
TURTLE_WORKING_DIR_PATH: path.join(os.homedir(), '.turtle/workingdir'),
EXPO_SKIP_SOURCING: '1',
};
export function initOfflineEnv() {
_.map(OFFLINE_ENV_VARS, (val, key) => {
process.env[key] = String(val);
});
}
-70
View File
@@ -1,70 +0,0 @@
import path from 'path';
import { LoggerDetach, ModuleVersion } from '@expo/xdl';
import program, { Command } from 'commander';
import fs from 'fs-extra';
import * as commands from 'turtle/bin/commands';
import logger from 'turtle/logger';
const { name, version } = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
const ModuleVersionChecker = ModuleVersion.createModuleVersionChecker(name, version);
LoggerDetach.configure(logger);
Command.prototype.asyncAction = function asyncAction(asyncFn: (...asyncFnArgs: any[]) => void): Command {
return this.action(async (...args) => {
try {
await checkForUpdateAsync();
} catch (err) {
logger.warn({ err }, 'Failed to check for turtle-cli update.');
}
return await asyncFn(...args);
});
};
export function run(programName: string) {
runAsync(programName).catch((err) => {
logger.error({ err }, 'Uncaught Error');
process.exit(1);
});
}
async function runAsync(programName: string) {
program.version(version);
Object.values(commands).forEach((command) => registerCommand(program, command));
program.parse(process.argv);
const subCommand = process.argv[2];
if (subCommand) {
const commandNames = program.commands.reduce((acc: string[], command: any) => {
acc.push(command._name);
const alias = command._alias;
if (alias) {
acc.push(alias);
}
return acc;
}, []);
if (!commandNames.includes(subCommand)) {
logger.error(
`"${subCommand}" is not an ${programName} command. See "${programName} --help" for the full list of commands.`,
);
}
} else {
program.help();
}
}
const registerCommand = (prog: any, command: any) => command(prog);
async function checkForUpdateAsync() {
const { updateIsAvailable, current, latest } = await ModuleVersionChecker.checkAsync();
if (updateIsAvailable) {
logger.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`,
);
}
}
-122
View File
@@ -1,122 +0,0 @@
import path from 'path';
import util from 'util';
import { ExponentTools } from '@expo/xdl';
import fs from 'fs-extra';
import _which from 'which';
import ensureAndroidNDKIsPresent from 'turtle/bin/setup/android/ndk';
import ensureAndroidSDKIsPresent from 'turtle/bin/setup/android/sdk';
import { checkSystem, ensureShellAppIsPresent } from 'turtle/bin/setup/utils/common';
import { IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';
import { formatShellAppDirectory } from 'turtle/builders/utils/android/workingdir';
import config from 'turtle/config';
import { PLATFORMS } from 'turtle/constants';
import logger from 'turtle/logger';
const which = util.promisify(_which);
const REQUIRED_TOOLS: IToolDefinition[] = [
{
command: 'bash',
missingDescription: 'Please install bash',
},
{
command: 'gulp',
missingDescription: 'Run `npm install -g gulp-cli` (or `yarn global add gulp-cli`) to install gulp',
},
{
command: 'javac',
missingDescription: 'Please install JDK (version 8 or newer) - check https://jdk.java.net/',
testFn: async () => {
const { status, stdout } = await ExponentTools.spawnAsyncThrowError(
'javac',
['-version'],
{ stdio: 'pipe' },
);
if (stdout.match(/no java runtime present/i)) {
return false;
}
return status === 0;
},
},
];
const LOGGER_FIELDS = { buildPhase: 'setting up environment' };
const l = logger.child(LOGGER_FIELDS);
export default async function setup(sdkVersion?: string) {
await checkSystem(REQUIRED_TOOLS);
await prepareAndroidEnv();
if (sdkVersion) {
await ensureShellAppIsPresent(
sdkVersion,
{ formatShellAppDirectory, formatShellAppTarballUriPath },
_shellAppPostDownloadAction,
);
}
}
async function prepareAndroidEnv() {
await fs.ensureDir(config.directories.androidDependenciesDir);
const sdkConfig = await ensureAndroidSDKIsPresent();
const ndkConfig = await ensureAndroidNDKIsPresent();
_setEnvVars({ ...sdkConfig.envVars, ...ndkConfig.envVars });
_alterPath([...sdkConfig.path, ...sdkConfig.path]);
}
function formatShellAppTarballUriPath(sdkMajorVersion: string) {
return path.join(config.directories.shellTarballsDir, PLATFORMS.ANDROID, `sdk${sdkMajorVersion}`);
}
async function _shellAppPostDownloadAction(sdkVersion: string, workingdir: string) {
const inWorkingdir = (filename: string) => path.join(workingdir, filename);
if (await fs.pathExists(inWorkingdir('universe-package.json'))) {
// legacy shell app built from universe
await fs.move(inWorkingdir('package.json'), inWorkingdir('exponent-package.json'));
await fs.move(inWorkingdir('universe-package.json'), inWorkingdir('package.json'));
await _installNodeModules(workingdir);
await fs.move(inWorkingdir('package.json'), inWorkingdir('universe-package.json'));
await fs.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 (ExponentTools.parseSdkMajorVersion(sdkVersion) < 33) {
const toolsPublicDir = path.join(workingdir, 'tools-public');
await _installNodeModules(toolsPublicDir);
}
}
async function _installNodeModules(cwd: string) {
l.info(`installing dependencies in ${cwd} directory...`);
const command = await _shouldUseYarnOrNpm();
await 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) {
Object
.entries(envVars)
.forEach(([key, value]) => process.env[key] = value);
}
function _alterPath(newPaths: string[]) {
const currentPaths = process.env.PATH ? process.env.PATH.split(':') : [];
const paths = [...newPaths, ...currentPaths];
process.env.PATH = paths.join(':');
}
-51
View File
@@ -1,51 +0,0 @@
import os from 'os';
import path from 'path';
import decompress from 'decompress';
import fs from 'fs-extra';
import { formatArtifactDownloadPath } from 'turtle/bin/setup/utils/common';
import download from 'turtle/bin/setup/utils/downloader';
import config from 'turtle/config';
import logger from 'turtle/logger';
const ANDROID_NDK_URL = `https://dl.google.com/android/repository/android-ndk-r10e-${os.platform()}-x86_64.zip`;
const LOGGER_FIELDS = { buildPhase: 'setting up environment' };
const l = logger.child(LOGGER_FIELDS);
export default async function ensureAndroidNDKIsPresent() {
const androidNdkDir = path.join(config.directories.androidDependenciesDir, 'ndk');
if (!(await fs.pathExists(androidNdkDir))) {
await fs.ensureDir(androidNdkDir);
const androidNdkDownloadPath = formatArtifactDownloadPath(ANDROID_NDK_URL);
try {
l.info('Downloading Android NDK');
await fs.ensureDir(config.directories.artifactsDir);
await download(ANDROID_NDK_URL, androidNdkDownloadPath);
l.info('Decompressing Android NDK');
await decompress(androidNdkDownloadPath, androidNdkDir, { strip: 1 });
l.info('Android NDK installed successfully');
} catch (err) {
await fs.remove(androidNdkDir);
throw err;
} finally {
await fs.remove(androidNdkDownloadPath);
}
}
return {
envVars: _createEnvVars(androidNdkDir),
path: _createPaths(androidNdkDir),
};
}
function _createEnvVars(androidNdkDir: string) {
return {
ANDROID_NDK: androidNdkDir,
};
}
function _createPaths(androidNdkDir: string) {
return [androidNdkDir];
}
-78
View File
@@ -1,78 +0,0 @@
import os from 'os';
import path from 'path';
import { ExponentTools } from '@expo/xdl';
import decompress from 'decompress';
import fs from 'fs-extra';
import { formatArtifactDownloadPath } from 'turtle/bin/setup/utils/common';
import download from 'turtle/bin/setup/utils/downloader';
import config from 'turtle/config';
import logger from 'turtle/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.child(LOGGER_FIELDS);
export default async function ensureAndroidSDKIsPresent() {
const androidSdkDir = path.join(config.directories.androidDependenciesDir, 'sdk');
if (!(await fs.pathExists(androidSdkDir))) {
await fs.ensureDir(androidSdkDir);
const androidSdkDownloadPath = formatArtifactDownloadPath(ANDROID_SDK_URL);
try {
l.info('Downloading Android SDK');
await fs.ensureDir(config.directories.artifactsDir);
await download(ANDROID_SDK_URL, androidSdkDownloadPath);
await fs.ensureDir(androidSdkDir);
l.info('Decompressing Android SDK');
await decompress(androidSdkDownloadPath, androidSdkDir);
await fs.remove(androidSdkDownloadPath);
l.info('Configuring Android SDK, this may take a while');
await _configureSdk(androidSdkDir);
l.info('Android SDK installed and configured successfully');
} catch (err) {
await fs.remove(androidSdkDir);
throw err;
} finally {
await fs.remove(androidSdkDownloadPath);
}
}
return {
envVars: _createEnvVars(androidSdkDir),
path: _createPaths(androidSdkDir),
};
}
async function _configureSdk(androidSdkDir: string) {
// prevents warnings about missing repo config
const androidRepositoriesCfgPath = path.join(os.homedir(), '.android/repositories.cfg');
await fs.ensureFile(androidRepositoriesCfgPath);
await ExponentTools.spawnAsyncThrowError('./configureAndroidSdk.sh', [], {
pipeToLogger: true,
loggerFields: LOGGER_FIELDS,
cwd: path.join(config.directories.rootDir, 'scripts/cli'),
env: {
...process.env,
ANDROID_HOME: androidSdkDir,
ANDROID_SDK: androidSdkDir,
},
});
}
function _createEnvVars(androidSdkDir: string) {
return {
ANDROID_HOME: androidSdkDir,
ANDROID_SDK: androidSdkDir,
};
}
function _createPaths(androidSdkDir: string) {
return [
path.join(androidSdkDir, 'platform-tools'),
path.join(androidSdkDir, 'tools'),
path.join(androidSdkDir, 'tools/bin'),
path.join(androidSdkDir, 'build-tools/28.0.3'),
];
}
-75
View File
@@ -1,75 +0,0 @@
import last from 'lodash/last';
import trim from 'lodash/trim';
import path from 'path';
import semver from 'semver';
import { ExponentTools } from '@expo/xdl';
import { checkSystem, ensureShellAppIsPresent } from 'turtle/bin/setup/utils/common';
import { IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';
import { formatShellAppDirectory } from 'turtle/builders/utils/ios/workingdir';
import config from 'turtle/config';
import { PLATFORMS } from 'turtle/constants';
const REQUIRED_TOOLS: IToolDefinition[] = [
{
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 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.satisfies(fastlaneVersion, `>= ${MINIMAL_VERSION}`)) {
throw new Error(
`Your fastlane 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 ExponentTools.spawnAsyncThrowError(
'xcodebuild',
['-version'],
{ stdio: 'pipe' },
);
if (stdout.match(/requires xcode/i)) {
return false;
}
return status === 0;
},
},
];
export default async function setup(sdkVersion?: string) {
await checkSystem(REQUIRED_TOOLS);
if (sdkVersion) {
await ensureShellAppIsPresent(sdkVersion, {
formatShellAppDirectory,
formatShellAppTarballUriPath,
});
}
}
function formatShellAppTarballUriPath(sdkMajorVersion: string) {
return path.join(config.directories.shellTarballsDir, PLATFORMS.IOS, `sdk${sdkMajorVersion}`);
}
function parseFastlaneVersion(stdout: string) {
const lastLine = last(trim(stdout).split('\n'));
if (!lastLine) {
return null;
}
return last(lastLine.split(' ')) || null;
}
-19
View File
@@ -1,19 +0,0 @@
import isSemver from 'is-semver';
import setupAndroid from 'turtle/bin/setup/android';
import setupIos from 'turtle/bin/setup/ios';
import { PLATFORMS } from 'turtle/constants';
export default async function setup(platform: string, sdkVersion?: string) {
if (sdkVersion && !isSemver(sdkVersion)) {
throw new Error('SDK version is not valid.');
}
if (platform === PLATFORMS.IOS) {
return await setupIos(sdkVersion);
} else if (platform === PLATFORMS.ANDROID) {
return await setupAndroid(sdkVersion);
} else {
throw new Error('This should never happen :(');
}
}
-67
View File
@@ -1,67 +0,0 @@
import path from 'path';
import { ExponentTools } from '@expo/xdl';
import fs from 'fs-extra';
import tar from 'tar';
import download from 'turtle/bin/setup/utils/downloader';
import { ensureToolsAreInstalled, IToolDefinition } from 'turtle/bin/setup/utils/toolsDetector';
import { IShellAppDirectoryConfig } from 'turtle/builders/utils/workingdir';
import config from 'turtle/config';
import logger from 'turtle/logger';
const l = logger.child({ buildPhase: 'setting up environment' });
interface IShellAppFormaters {
formatShellAppDirectory: (config: IShellAppDirectoryConfig) => string;
formatShellAppTarballUriPath: (sdkMajorVersion: string) => string;
}
type PostDownloadAction = (sdkVersion: string, workingdir: string) => void;
export async function checkSystem(requiredTools: IToolDefinition[]) {
await ensureToolsAreInstalled(requiredTools);
}
export async function ensureShellAppIsPresent(
sdkVersion: string,
formatters: IShellAppFormaters,
postDownloadAction?: PostDownloadAction,
) {
const workingdir = formatters.formatShellAppDirectory({ sdkVersion });
if (await fs.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);
}
}
async function _downloadShellApp(sdkVersion: string, targetDirectory: string, formatters: IShellAppFormaters) {
const shellAppTarballS3Uri = await _readShellAppTarballS3Uri(sdkVersion, formatters);
const tarballDownloadTargetPath = formatArtifactDownloadPath(shellAppTarballS3Uri);
await fs.ensureDir(config.directories.artifactsDir);
await download(shellAppTarballS3Uri, tarballDownloadTargetPath);
l.info('shell app has been downloaded');
await fs.ensureDir(targetDirectory);
l.info('extracting shell app (this may take a while)...');
await tar.x({
file: tarballDownloadTargetPath,
C: targetDirectory,
});
l.info('shell app extracted');
}
export function formatArtifactDownloadPath(uri: string) {
const { base } = path.parse(uri);
return path.join(config.directories.artifactsDir, base);
}
async function _readShellAppTarballS3Uri(sdkVersion: string, formatters: IShellAppFormaters) {
const sdkMajorVersion = ExponentTools.parseSdkMajorVersion(sdkVersion);
const filePath = formatters.formatShellAppTarballUriPath(sdkMajorVersion);
const data = await fs.readFile(filePath, 'utf8');
return data.trim();
}
-47
View File
@@ -1,47 +0,0 @@
import fs from 'fs';
import { URL } from 'url';
import ProgressBar from 'progress';
import request from 'request';
import requestProgress from 'request-progress';
const S3_PROTOCOL = 's3:';
const PROGRESS_BAR_CONFIG = {
TEMPLATE: 'downloading [:bar] :percent :etas',
BAR: {
COMPLETE_CHAR: '=',
INCOMPLETE_CHAR: ' ',
WIDTH: 20,
},
};
export default async function download(url: string, destPath: string) {
const httpUrl = url.startsWith(S3_PROTOCOL) ? convertS3ToHttpsUrl(url) : url;
let bar: ProgressBar;
return new Promise((res, rej) => {
requestProgress(request(httpUrl))
.on('progress', (state: any) => {
if (!bar) {
bar = new ProgressBar(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 as any).curr);
})
.on('error', (err: Error) => rej(err))
.on('end', () => res())
.pipe(fs.createWriteStream(destPath));
});
}
function convertS3ToHttpsUrl(s3UrlRaw: string) {
const { host: s3Bucket, pathname: s3Path, protocol } = new URL(s3UrlRaw);
if (protocol !== S3_PROTOCOL) {
throw new Error('Wrong S3 URL provided');
}
return `https://${s3Bucket}.s3.amazonaws.com${s3Path}`;
}
-46
View File
@@ -1,46 +0,0 @@
import util from 'util';
import _which from 'which';
import logger from 'turtle/logger';
const which = util.promisify(_which);
const l = logger.child({ buildPhase: 'setting up environment' });
export interface IToolDefinition {
command: string;
missingDescription: string;
testFn?: () => Promise<boolean>;
versionCheckFn?: () => void;
}
export async function ensureToolsAreInstalled(tools: IToolDefinition[]) {
let isAnyToolMissing = false;
for (const { command, missingDescription, testFn, versionCheckFn } of tools) {
try {
if (testFn) {
if (!await testFn()) {
throw new Error('Required tool doesn\'t exist');
}
} 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.');
}
}
-84
View File
@@ -1,84 +0,0 @@
import _ from 'lodash';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';
import setup from 'turtle/bin/setup/setup';
import * as ProjectUtils from 'turtle/bin/utils/project';
import * as UserUtils from 'turtle/bin/utils/user';
import logger from 'turtle/logger';
import { sanitizeJob } from 'turtle/validator';
export function createBuilderAction({
program,
command,
prepareCredentials,
buildJobObject,
builder,
platform,
os,
}: any) {
return async (projectDirArg: string, cmd: any) => {
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(
'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('You must provide both Expo username and password');
}
} else if (!cmd.publicUrl) {
throw new ErrorWithCommandHelp(
'You must provide your Expo username and password unless you specify --public-url to your project manifest.',
);
}
const args = {
releaseChannel: cmd.releaseChannel || 'default',
buildType: cmd.type,
username: userData.username || 'anonymous',
projectDir: ProjectUtils.resolveAbsoluteDir(projectDirArg),
publicUrl: cmd.publicUrl,
};
const appJSON = await ProjectUtils.loadAppJSON(projectDirArg, cmd.config);
const sdkVersion = _.get(appJSON, 'expo.sdkVersion');
await setup(platform, sdkVersion);
const credentials = await prepareCredentials(cmd);
const rawJob = {
...buildJobObject(appJSON, args, credentials),
...cmd.buildDir && { fakeUploadDir: ProjectUtils.resolveAbsoluteDir(cmd.buildDir) },
...cmd.output && { fakeUploadBuildPath: ProjectUtils.resolveAbsoluteDir(cmd.output) },
};
const job = await sanitizeJob(rawJob);
await builder(job);
} catch (err) {
logger.error({ err }, 'Failed to build standalone app');
if (err instanceof ErrorWithCommandHelp) {
command.help();
} else if (err instanceof ErrorWithProgramHelp) {
program.help();
}
process.exit(1);
}
};
}
-27
View File
@@ -1,27 +0,0 @@
import fs from 'fs-extra';
import path from 'path';
export async function loadAppJSON(projectDirArg: string, config: string | null) {
let appJSONPath;
if (config) {
appJSONPath = resolveAbsoluteDir(config);
} else {
const projectDir = resolveAbsoluteDir(projectDirArg);
appJSONPath = path.join(projectDir, 'app.json');
}
const appJSONExists = await fs.pathExists(appJSONPath);
if (!appJSONExists) {
throw new Error(`Couldn't find app.json.`);
} else {
return require(appJSONPath);
}
}
export const resolveAbsoluteDir = (dir: string) => {
if (dir && path.isAbsolute(dir)) {
return dir;
} else {
const cwd = process.env.INIT_CWD || process.cwd();
return dir ? path.join(cwd, dir) : cwd;
}
};
-23
View File
@@ -1,23 +0,0 @@
import { User as UserManager } from '@expo/xdl';
import { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';
interface IUserData {
username?: string;
password?: string;
}
export async function ensureUserLoggedIn(userData: IUserData) {
const currentUser = await UserManager.getCurrentUserAsync();
if (currentUser) {
return currentUser;
} else if (!userData.username || !userData.password) {
throw new ErrorWithProgramHelp('Please provide username and password');
} else {
try {
return await UserManager.loginAsync('user-pass', userData);
} catch (err) {
throw new Error('Failed to log in with provided username and password');
}
}
}
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff. Show more