mirror of
https://github.com/expo/turtle.git
synced 2026-11-14 19:12:55 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ac87171d0 | ||
|
|
7af5a01c17 | ||
|
|
23fbf5ffb4 | ||
|
|
7a80d92e72 | ||
|
|
1a2a7654c2 | ||
|
|
a5aaa46790 | ||
|
|
1691655f61 | ||
|
|
f38ab7c9ee | ||
|
|
8fd8a6e70e | ||
|
|
43a319b12b | ||
|
|
511f58e6ec | ||
|
|
350f68e330 | ||
|
|
851b0a62ab | ||
|
|
d97f290ce1 | ||
|
|
2feb10aeec | ||
|
|
8a288c271a | ||
|
|
47fe68abbd | ||
|
|
51d00a8706 | ||
|
|
3f25edccd7 | ||
|
|
2f10ab1bc9 | ||
|
|
4f8c21a075 | ||
|
|
7179f6019c | ||
|
|
2bbf2d7784 | ||
|
|
3ccb4c994e | ||
|
|
46706a7cdb | ||
|
|
383358b11d | ||
|
|
a87cc75b5d | ||
|
|
391a3a9937 | ||
|
|
7cfedbc448 | ||
|
|
9b6eb8b66a | ||
|
|
c52a126409 | ||
|
|
908ab0f74d | ||
|
|
ab15d4c407 | ||
|
|
9f7b77a09c | ||
|
|
67260647ff | ||
|
|
849759c6c5 | ||
|
|
fdcf67c96f | ||
|
|
407db0efb6 | ||
|
|
8ec619a627 | ||
|
|
849e026833 | ||
|
|
13652b0e07 | ||
|
|
06c2c71515 | ||
|
|
5f98e9f5ce | ||
|
|
f314ef17dd | ||
|
|
30274bfd7e | ||
|
|
8ef99f2eae | ||
|
|
855e4bb962 | ||
|
|
df789b2de7 | ||
|
|
eff0556291 | ||
|
|
db74843ae0 | ||
|
|
a0e1382531 | ||
|
|
952dcd0cd3 | ||
|
|
0cd4e2953a | ||
|
|
a03d93cb27 | ||
|
|
010e92472b | ||
|
|
75316b5f07 | ||
|
|
4baa49e8fe | ||
|
|
edb167e6b1 | ||
|
|
d552b97654 | ||
|
|
12718c0b36 | ||
|
|
f9600f26e8 | ||
|
|
68f9744f7b | ||
|
|
8c2031c3d7 | ||
|
|
3165b5346e | ||
|
|
1552c9e7f2 | ||
|
|
51a0e772c0 | ||
|
|
98747c1db6 | ||
|
|
4f64aa2617 | ||
|
|
1f487d39fb | ||
|
|
f7e647c1f4 | ||
|
|
d900e3c491 | ||
|
|
32b049df86 | ||
|
|
723c84b575 | ||
|
|
0ab4d2ed90 | ||
|
|
05b96a5b6f | ||
|
|
5467aca0fb | ||
|
|
cf1e1daa26 | ||
|
|
8649968531 | ||
|
|
b89214fcc9 | ||
|
|
0142147a61 | ||
|
|
331c8edba7 | ||
|
|
ed382e0d2c | ||
|
|
3f0958845d | ||
|
|
6e345757e3 | ||
|
|
3588c5a5c4 | ||
|
|
1f94e38e60 | ||
|
|
ca8465d2a1 | ||
|
|
fe31b74471 | ||
|
|
ed12f3c34b | ||
|
|
9cf607ef13 | ||
|
|
9287d1254e | ||
|
|
97977d895f | ||
|
|
30d083ad62 | ||
|
|
a3f01334df | ||
|
|
65f1eea647 | ||
|
|
2a739dc5ab | ||
|
|
201b28e6a8 | ||
|
|
55eaa18fde | ||
|
|
8ba0f61c6f | ||
|
|
b9d0f12cac | ||
|
|
6c2c55b650 | ||
|
|
9e13991f63 | ||
|
|
2b7c7bb3ff | ||
|
|
128371e452 | ||
|
|
19a668e541 | ||
|
|
8751e7a8be | ||
|
|
31dce0a9f5 | ||
|
|
46a83d7c7c | ||
|
|
f0ecda40e8 | ||
|
|
3c92005a3d | ||
|
|
9c6a3a4e39 | ||
|
|
71cd699488 | ||
|
|
9480a51059 | ||
|
|
dd7a803116 | ||
|
|
5f5cd6ac59 | ||
|
|
5552317fb8 | ||
|
|
4aebb52523 | ||
|
|
d22722bc33 | ||
|
|
7f432f453f | ||
|
|
44b2b0a9be | ||
|
|
30789e939e | ||
|
|
60a12f6710 | ||
|
|
838f628ddd | ||
|
|
294a3df7b4 | ||
|
|
6bfcbbb663 | ||
|
|
50e026d311 | ||
|
|
4dcb0b71be | ||
|
|
8bb527f04c | ||
|
|
1e7db2c92f | ||
|
|
4d761dd293 | ||
|
|
a40546606f | ||
|
|
fbd7fcb4f8 | ||
|
|
a59ce7a7ee | ||
|
|
e850bae696 | ||
|
|
c0cf273b7c | ||
|
|
cbb8faef12 | ||
|
|
d24b82b5c2 | ||
|
|
3f5ddf6a22 | ||
|
|
80f30bb29c | ||
|
|
c6e2b07fff | ||
|
|
80b0029d57 | ||
|
|
17bda59676 | ||
|
|
2fbcbaa525 | ||
|
|
22e47e4e43 | ||
|
|
1d4728e402 | ||
|
|
de4837f361 | ||
|
|
20d393e48e | ||
|
|
95714bdf5e | ||
|
|
8e2b593e3e | ||
|
|
885cf08a9d | ||
|
|
bd816e1124 | ||
|
|
98549f147c | ||
|
|
9de691c60e | ||
|
|
71e270dc50 | ||
|
|
26e684069d | ||
|
|
1c67df516e | ||
|
|
d7ed489876 | ||
|
|
267e487494 | ||
|
|
b07d830eb9 | ||
|
|
bfaaf09e57 | ||
|
|
33b2a569aa | ||
|
|
2febf6bcdd | ||
|
|
e2c9ee0e39 | ||
|
|
f017540571 | ||
|
|
5b65eb3d6e | ||
|
|
60874f31c9 | ||
|
|
78beb3c0b3 | ||
|
|
03633d94e5 | ||
|
|
392e4487b7 | ||
|
|
f316cb0e0c | ||
|
|
968ce7d8bb | ||
|
|
5876a11568 | ||
|
|
7448e1f4e4 | ||
|
|
4338e71005 | ||
|
|
7323412095 | ||
|
|
c1d5a17e45 | ||
|
|
2771ad0829 | ||
|
|
32cc988072 | ||
|
|
0b3ce2c8e0 | ||
|
|
9c46ee143e | ||
|
|
31c17a4d72 | ||
|
|
ee3f265294 | ||
|
|
c1cca91e68 | ||
|
|
038bafe20b | ||
|
|
f2fef264d7 | ||
|
|
fae77b4455 | ||
|
|
a3ffa0411e | ||
|
|
27dd680cbd | ||
|
|
2b5a370f48 | ||
|
|
21933f5a6a | ||
|
|
a5bd4f0c97 | ||
|
|
8e10aacf59 | ||
|
|
3dd74ef406 | ||
|
|
87f7085fc4 | ||
|
|
0b0b5a7c72 | ||
|
|
d6dee79bcf | ||
|
|
db05eeeed3 | ||
|
|
cc317a6572 | ||
|
|
149073466d | ||
|
|
776aec445b | ||
|
|
d6432b6455 | ||
|
|
81f3a0e300 | ||
|
|
167766519e | ||
|
|
b0d7156691 | ||
|
|
0fdf722a48 | ||
|
|
0382e6bc18 | ||
|
|
07a72ea5cb | ||
|
|
1d3647db98 | ||
|
|
53b96d399f | ||
|
|
78067fc8a6 | ||
|
|
4b29da8f5b | ||
|
|
74d6b37b00 | ||
|
|
d8049d8b83 | ||
|
|
226e0fe899 | ||
|
|
6fe9106de6 | ||
|
|
7ae44b4093 | ||
|
|
34e397352b | ||
|
|
1f8017de54 | ||
|
|
671c7e8ae6 | ||
|
|
69fd839049 | ||
|
|
55f0a94560 | ||
|
|
53020e7d73 | ||
|
|
8d78d55ae2 | ||
|
|
483df86e7c |
No files matched your search
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"node": "8.9"
|
||||
}
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["module-resolver", {
|
||||
"alias": {
|
||||
"turtle": "./build"
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
+268
-16
@@ -1,29 +1,281 @@
|
||||
version: 2
|
||||
version: 2.1
|
||||
|
||||
machine:
|
||||
node:
|
||||
# Circle will use node v4.0.0
|
||||
version: 4.0.0
|
||||
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 >>"
|
||||
|
||||
deploy_turtle:
|
||||
parameters:
|
||||
platform:
|
||||
type: string
|
||||
env:
|
||||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install curl & jq
|
||||
command: nix-env -iA nixpkgs.curl nixpkgs.jq
|
||||
- run:
|
||||
name: Schedule a Turtle deploy
|
||||
command: |
|
||||
echo "We're going to deploy << parameters.platform >> Turtles to << parameters.env >>"
|
||||
./scripts/deploy.sh "<< parameters.platform >>" "<< parameters.env >>"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:10.15.0
|
||||
executor: nix
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- restore_yarn_cache
|
||||
- run: yarn
|
||||
- save_yarn_cache
|
||||
- run: yarn lint
|
||||
- run: yarn build
|
||||
test:
|
||||
docker:
|
||||
- image: circleci/node:10.15.0
|
||||
|
||||
unit_tests:
|
||||
executor: nix
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- restore_yarn_cache
|
||||
- run: yarn
|
||||
- run: ./test-ci-unit.sh
|
||||
- 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
|
||||
|
||||
android_staging_deploy:
|
||||
executor: nix
|
||||
steps:
|
||||
- deploy_turtle:
|
||||
platform: android
|
||||
env: staging
|
||||
|
||||
android_production_deploy:
|
||||
executor: nix
|
||||
steps:
|
||||
- deploy_turtle:
|
||||
platform: android
|
||||
env: production
|
||||
|
||||
ios_staging_deploy:
|
||||
executor: nix
|
||||
steps:
|
||||
- deploy_turtle:
|
||||
platform: ios
|
||||
env: staging
|
||||
|
||||
ios_production_deploy:
|
||||
executor: nix
|
||||
steps:
|
||||
- deploy_turtle:
|
||||
platform: ios
|
||||
env: production
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
checks:
|
||||
jobs:
|
||||
- build
|
||||
- test
|
||||
tests:
|
||||
jobs:
|
||||
- unit_tests
|
||||
- ios_smoke_tests
|
||||
- android_smoke_tests
|
||||
deploy:
|
||||
jobs:
|
||||
- android_staging_approve_deploy:
|
||||
type: approval
|
||||
- android_staging_deploy:
|
||||
requires:
|
||||
- android_staging_approve_deploy
|
||||
- android_production_approve_deploy:
|
||||
type: approval
|
||||
- android_production_deploy:
|
||||
requires:
|
||||
- android_production_approve_deploy
|
||||
- ios_staging_approve_deploy:
|
||||
type: approval
|
||||
- ios_staging_deploy:
|
||||
requires:
|
||||
- ios_staging_approve_deploy
|
||||
- ios_production_approve_deploy:
|
||||
type: approval
|
||||
- ios_production_deploy:
|
||||
requires:
|
||||
- ios_production_approve_deploy
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source_local() {
|
||||
file=./.envrc.local
|
||||
@@ -8,11 +8,20 @@ source_local() {
|
||||
watch_file $file
|
||||
}
|
||||
|
||||
source_up || true
|
||||
source_local
|
||||
|
||||
if [[ "$CI" != "true" && (-z "$GITHUB_TOKEN" || -z "$CIRCLE_API_USER_TOKEN") ]]; then
|
||||
yellow=`tput setaf 3`
|
||||
reset=`tput sgr0`
|
||||
echo "${yellow}please set GITHUB_TOKEN and CIRCLE_API_USER_TOKEN env variables in .envrc.local file if you wish to release turtle-cli"
|
||||
echo "run 'cp .envrc.local.example .envrc.local' if you don't have one yet and edit the new file${reset}"
|
||||
fi
|
||||
|
||||
export NODE_ENV=development
|
||||
|
||||
export EXPO_TURTLE_TOOLS_DIR="$(pwd)/tools"
|
||||
|
||||
PATH_add $EXPO_TURTLE_TOOLS_DIR/bin
|
||||
if [ "$CI" = "true" ]; then
|
||||
PATH_add $EXPO_TURTLE_TOOLS_DIR/ci/bin
|
||||
fi
|
||||
@@ -0,0 +1,2 @@
|
||||
export GITHUB_TOKEN=__PUT_YOUR_GITHUB_TOKEN_HERE__ # follow the guide to create one: https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line
|
||||
export CIRCLE_API_USER_TOKEN=__PUT_YOUR_CIRCLECI_API_TOKEN_HERE__ # create one here: https://circleci.com/account/api
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"import"
|
||||
],
|
||||
"extends": ["universe", "plugin:import/errors"],
|
||||
"rules":{
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": ["builtin", "external", "parent", "sibling", "index"],
|
||||
"newlines-between": "always"
|
||||
}
|
||||
],
|
||||
"import/no-unresolved": "off"
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"babel-module": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: "\U0001F41B Bug Report"
|
||||
about: You want to report a reproducible bug or regression in turtle-cli.
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Thanks for helping expo! Before you submit your issue, please make sure you followed our checklist and check the appropriate boxes by putting an x in the [ ]: [x] -->
|
||||
|
||||
### New Issue Checklist
|
||||
|
||||
- [ ] Updated turtle-cli to the latest version (`yarn global add turtle-cli` or `npm install --global turtle-cli`).
|
||||
- [ ] I read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
|
||||
- [ ] I read [docs.expo.io](https://docs.expo.io) (Managed Workflow > Distributing Your App).
|
||||
- [ ] I searched for [existing GitHub issues](https://github.com/expo/turtle/issues).
|
||||
- [ ] **I enclosed the complete output when running turtle, including the stack trace and command used.**
|
||||
|
||||
### Issue Description
|
||||
<!-- Please include what's happening, expected behavior, and any relevant code samples -->
|
||||
|
||||
##### Command executed
|
||||
<!-- The command you executed on the command line that resulted in an error -->
|
||||
|
||||
##### Complete output when running turtle, including the stack trace and command used
|
||||
|
||||
<details>
|
||||
<pre> [PUT LOGS HERE] </pre>
|
||||
</details>
|
||||
|
||||
### Environment
|
||||
|
||||
<!-- Please run `expo diagnostics` and copy the output below. This will help us help you. -->
|
||||
|
||||
<details>
|
||||
<pre> [PUT OUTPUT HERE] </pre>
|
||||
</details>
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: "\U0001F64B Feature Request"
|
||||
about: Want us to add something to turtle-cli?
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Feature Request
|
||||
|
||||
#### Motivation Behind Feature
|
||||
<!-- Why should this feature be implemented? What problem does it solve? -->
|
||||
|
||||
#### Feature Description
|
||||
<!-- Describe your feature request in detail -->
|
||||
<!-- Please provide any code examples or screenshots of what this feature would look like -->
|
||||
<!-- Are there any drawbacks? Will this break anything for existing users? -->
|
||||
|
||||
#### Alternatives or Workarounds
|
||||
<!-- Describe alternatives or workarounds you are currently using -->
|
||||
<!-- Are there ways to do this with existing commands? -->
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: "\U00002753 Questions and discussions"
|
||||
about: You have a question about turtle-cli or want to discuss some aspects of turtle-cli.
|
||||
title: ''
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Question Checklist
|
||||
|
||||
- [ ] I read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
|
||||
- [ ] I read [docs.expo.io](https://docs.expo.io) (Managed Workflow > Distributing Your App).
|
||||
- [ ] I searched for [existing GitHub issues](https://github.com/expo/turtle/issues).
|
||||
|
||||
### Question Subject
|
||||
<!-- What command do you have a question about? -->
|
||||
<!-- Is this a question about documentation? -->
|
||||
|
||||
#### Question Description
|
||||
<!-- Please include expected behavior and any relevant code samples with your question if possible -->
|
||||
@@ -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.
|
||||
@@ -0,0 +1,15 @@
|
||||
<!-- Thanks for contributing to _turtle_! Before you submit your pull request, please make sure to check the following boxes by putting an x in the [ ] (don't: [x ], [ x], do: [x]) -->
|
||||
|
||||
### Checklist
|
||||
- [ ] I've read the [Contribution Guidelines](https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
|
||||
- [ ] I've updated the [CHANGELOG](https://github.com/expo/turtle/blob/master/CHANGELOG.md) if necessary.
|
||||
- [ ] I've ensured the unit and smoke tests are still passing - either by running `yarn test:unit` and `yarn test:smoke:[ios|android]` or by checking the appropriate CircleCI builds' statuses.
|
||||
- [ ] **I've manually tested whether the changes I made work as expected.**
|
||||
|
||||
### Motivation and Context
|
||||
<!-- Why is this change required? What problem does it solve? -->
|
||||
<!-- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
### Description
|
||||
<!-- Describe your changes in detail -->
|
||||
<!-- Please describe in detail how you tested your changes. -->
|
||||
+9
-1
@@ -1,8 +1,16 @@
|
||||
!/src/node_modules
|
||||
|
||||
node_modules
|
||||
yarn-error.log
|
||||
google-cloud-credentials.json
|
||||
|
||||
/build/
|
||||
/workingdir/*
|
||||
/artifacts/*
|
||||
shell.apk
|
||||
node_modules
|
||||
.secrets*
|
||||
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
.envrc.local
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"commit": false,
|
||||
"tag": true,
|
||||
"push": true,
|
||||
"requireUpstream": false,
|
||||
"tagName": "v${version}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"npm": {
|
||||
"tag": "latest"
|
||||
},
|
||||
"git": {
|
||||
"requireUpstream": false,
|
||||
"tagName": "v${version}"
|
||||
},
|
||||
"github": {
|
||||
"release": true
|
||||
},
|
||||
"hooks": {
|
||||
"after:release": "yarn release:update:turtle-cli-example"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ LOGGER_LEVEL="debug"
|
||||
API_PROTOCOL="http"
|
||||
API_HOSTNAME="localhost"
|
||||
API_PORT="3000"
|
||||
LOGGLY_TOKEN=""
|
||||
SENTRY_DSN=""
|
||||
ENVIRONMENT="development"
|
||||
REDIS_URL="redis://localhost:6379/0"
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
# 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
|
||||
- Enabled back optional modules support, but only for specific unimodules.
|
||||
- Updated SDK34 Android shell app with latest fixes (up to 2.12.2)
|
||||
- Updated SDK34 iOS shell app with latest fixes (up to 2.12.3)
|
||||
|
||||
## [0.10.0] - 2019-08-01
|
||||
### Changed
|
||||
- Fully disabled optional modules on Android for now.
|
||||
- Updated iOS shell apps for SDK 33 and 34 to fix scoped permissions issue.
|
||||
- Updated Android shell app for SDK 34 to work after disabling optional modules.
|
||||
|
||||
## [0.9.1] - 2019-07-29
|
||||
### Changed
|
||||
- `release-it` version to `12.3.4`.
|
||||
|
||||
## [0.9.0] - 2019-07-29
|
||||
### Added
|
||||
- Android, iOS standalone shell apps and iOS Expo client shell app for SDK34.
|
||||
- Xcode license check for iOS builds.
|
||||
### Fixed
|
||||
- Setting `Constants.nativeAppVersion` for Android standalone builds (actually fixed in [expo/expo-cli#878](https://github.com/expo/expo-cli/pull/878)).
|
||||
- Passing `expo.android.config` object from `app.json` to the Android builder.
|
||||
|
||||
## [0.8.11] - 2019-07-16
|
||||
### Fixed
|
||||
- Android debug builds.
|
||||
|
||||
## [0.8.10] - 2019-07-16
|
||||
### Fixed
|
||||
- iOS simulator builds.
|
||||
|
||||
## [0.8.9] - 2019-07-15
|
||||
### Fixed
|
||||
- User authentication.
|
||||
|
||||
## [0.8.8] - 2019-07-11
|
||||
### Fixed
|
||||
- LocalAuthentication module on iOS (fixes [expo/expo#663](https://github.com/expo/expo/issues/663)).
|
||||
|
||||
## [0.8.7] - 2019-07-05
|
||||
### Added
|
||||
- Adhoc Builds: use provisioningProfileId if specified.
|
||||
- Registering supported SDK versions in Redis.
|
||||
- Support for 64 bit builds in SDK33.
|
||||
|
||||
## [0.8.6] - 2019-06-25
|
||||
### Added
|
||||
- Added support for Android build modes: debug or release.
|
||||
### Fixed
|
||||
- Upgrading the shell app for a given SDK version when the previous version is already downloaded (bug in `turtle-cli`).
|
||||
- Updated Android shell app for SDK33 to include `[email protected]` which fixes crashes on Android 9.0 when showing some Lottie animations.
|
||||
- Schema for `buildModes`.
|
||||
- Updated @expo/xdl to 55.0.7 (fixed reading from binary plist).
|
||||
|
||||
## [0.8.4] - 2019-06-13
|
||||
### Changed
|
||||
- Upgraded `sharp` from `0.21.3` to `0.22.1`.
|
||||
- `gulp-cli` is no longer required to build an app with `turtle-cli`.
|
||||
|
||||
## [0.8.3] - 2019-06-13
|
||||
### Added
|
||||
- Running Android Turtle process with `supervisor` (pod is restarted if there were 5 failures in the last 10 minutes).
|
||||
### Changed
|
||||
- `turtle-cli` is now fetching the app manifest before running the build.
|
||||
|
||||
## [0.8.2] - 2019-06-11
|
||||
### Changed
|
||||
- Updated Android shell app for SDK33 to remove `expo-face-detector` and `expo-payments-stripe` from standalone builds.
|
||||
- Updated Android shell app for SDK33 to get rid of `node_modules` for `tools-public`.
|
||||
- From now on, `turtle-cli` installs dependencies for `tools-public` in shell apps for SDK versions < 33.
|
||||
### Fixed
|
||||
- Android builds with turtle-cli by installing all unmodules if `dependencies` is empty.
|
||||
|
||||
## [0.8.1] - 2019-06-10
|
||||
### Changed
|
||||
- Add expo dependencies when resolving unimodules.
|
||||
### Fixed
|
||||
- Support for Android tarballs without `universe-package.json`.
|
||||
|
||||
## [0.8.0] - 2019-06-07
|
||||
### Added
|
||||
- Turtle CLI logo to the project (created by [@zularizal](https://github.com/zularizal))!
|
||||
- Shell apps for SDK 33.
|
||||
- Support for Android App Bundles (App bundles are built by default, use `-t apk` to build apk).
|
||||
### Changed
|
||||
- Updated Android shell app for SDK 32 to fix AppAuth issue (https://github.com/expo/expo/pull/4115) and to fix a newer than expected JSC version.
|
||||
- Default value for build timeout to 15 minutes.
|
||||
- Added filtering of logs (strips out download progress) when downloading SDK tools.
|
||||
- `xdl` -> `@expo/xdl`, updated `@expo/xdl`.
|
||||
### Fixed
|
||||
- Generating Android keystore in turtle when one is not passed to turtle-cli (https://github.com/expo/turtle/pull/65).
|
||||
- Upload logs to s3 if build has been canceled or timed out.
|
||||
- Unhandled exception on asset download (xdl).
|
||||
|
||||
## [0.7.2] - 2019-05-09
|
||||
### Added
|
||||
- Support for Android tarballs without `universe-package.json`.
|
||||
### Changed
|
||||
- Upgraded `@expo/traveling-fastlane-darwin` to 1.9.4 (fixes issues with generating provisioning profiles for ad-hoc builds).
|
||||
### Removed
|
||||
- Support for `CLIENT_LOGGER_LEVEL` env variable.
|
||||
|
||||
## [0.7.1] - 2019-05-06
|
||||
### Fixed
|
||||
- Resolving `fastlane` version when `LC_ALL` is not set.
|
||||
|
||||
## [0.7.0] - 2019-05-06
|
||||
### Added
|
||||
- Support for custom Android builds.
|
||||
### Changed
|
||||
- Refactored logger.
|
||||
### Fixed
|
||||
- `platform` log field wrongly set to `ios` for Android builds (when using `turtle-cli`).
|
||||
- Brought back `jobID` and `experienceName` fields to Android logs.
|
||||
|
||||
## [0.6.1] - 2019-04-23
|
||||
### Added
|
||||
- Checking fastlane version before running build (turtle-cli).
|
||||
### Changed
|
||||
- Updated iOS shell app for SDK 32 to fix AppAuth issue.
|
||||
- Babel replaced by ttypescript.
|
||||
- Updated xdl to 53.5.3 and @expo/spawn-async to 1.4.2, so that error stack traces should be more informative now.
|
||||
### Fixed
|
||||
- Brought back `jobID` and `experienceName` fields to GCloud logs.
|
||||
### Removed
|
||||
- `buidAndroidTarballLocally.sh` script (it has been moved to expo repository - [expo/expo#4022](https://github.com/expo/expo/pull/4022)).
|
||||
|
||||
## [0.6.0] - 2019-04-09
|
||||
### Changed
|
||||
- Removed Branch module from Android shell apps for all SDK versions.
|
||||
|
||||
## [0.5.15] - 2019-04-03
|
||||
### Added
|
||||
- Turtle smoke tests are now being executed on CircleCI from the context of this repository.
|
||||
### Changed
|
||||
- Updated iOS shell app for SDK 32 (fixes [this loading issue for slow connections](https://github.com/expo/expo/issues/3574)).
|
||||
- Minor infra changes (doesn't affect users).
|
||||
- Error logs format - error objects are now passed in an object being passed as the first argument to logger function.
|
||||
### Removed
|
||||
- Sending logs to loggly.
|
||||
|
||||
## [0.5.14] - 2019-03-22
|
||||
### Added
|
||||
- `--config` parameter for turtle-cli commands, which allows to specify a custom path to app.json file
|
||||
### Changed
|
||||
- Updated iOS shell app for SDK 32 (fixes [this notifications issue](https://github.com/expo/expo/issues/3663)).
|
||||
|
||||
## [0.5.13] - 2019-03-12
|
||||
### Added
|
||||
- Android SDK version support validation.
|
||||
### Changed
|
||||
- iOS Enterprise builds don't compile bitcode now.
|
||||
|
||||
## [0.5.12] - 2019-02-26
|
||||
### Added
|
||||
- Google Cloud logger (as a bunyan stream).
|
||||
### Changed
|
||||
- Android builder passes the manifest from a build job message if it's available.
|
||||
|
||||
## [0.5.11] - 2019-02-22
|
||||
### Added
|
||||
- Builder for iOS client apps.
|
||||
|
||||
## [0.5.10] - 2019-02-19
|
||||
### Added
|
||||
- Registering Turtle version in Redis.
|
||||
### Changed
|
||||
- Update Android shell app for SDK 32 to fix [update](https://github.com/expo/expo/issues/3504) and [back button](https://github.com/expo/expo/issues/1786) issues.
|
||||
|
||||
## [0.5.9] - 2019-02-06
|
||||
- Update iOS shell app for SDK 32 (fixes bare notifications [issue](https://github.com/expo/expo/issues/3223)).
|
||||
|
||||
## [0.5.7] - 2019-01-31
|
||||
- Update Android shell app for SDK 32 to fix bundled assets issue.
|
||||
|
||||
## [0.5.6] - 2019-01-25
|
||||
- Update iOS shell app for SDK 30, 31 and 32 (built with xcode 10.1).
|
||||
|
||||
## [0.5.5] - 2019-01-24
|
||||
### Added
|
||||
- Sending build duration in AWS SQS messages (of `FINISHED` and `ERRORED` types).
|
||||
|
||||
## [0.5.4] - 2019-01-22
|
||||
### Changed
|
||||
- Update iOS shell app for SDK32 to [`expo/expo#0847c10`](https://github.com/expo/expo/commit/0847c1073d38c366866f3d9279ddd662da47dc9b), i.e. v2.10.3 with fixed WebView navigation scheme and upgraded Facebook SDK.
|
||||
|
||||
## [0.5.3] - 2019-01-21
|
||||
### Fixed
|
||||
- Building Android standalone apps ([not accepted license issue](https://github.com/expo/expo/issues/3266)) - updated Android build tools (`build-tools;28.0.3`, `platforms;android-28`).
|
||||
|
||||
## [0.5.2] - 2019-01-18
|
||||
### Added
|
||||
- The link (in README) to the repository containing `turtle-cli` usage example.
|
||||
- [Contributing guide](CONTRIBUTING.md).
|
||||
- [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
### Removed
|
||||
- `eslint`
|
||||
### Changed
|
||||
- Fix all `tslint` errors.
|
||||
|
||||
## [0.5.1] - 2019-01-16
|
||||
### Changed
|
||||
- Update Android shell app for SDK32 that includes `[email protected]`.
|
||||
|
||||
## [0.5.0] - 2019-01-16
|
||||
### Added
|
||||
- Turtle version is added to the `onFinish` and `onError` build messages.
|
||||
### Changed
|
||||
- A version property value being sent to the queue. It's now the version number
|
||||
from `package.json` instead of `new`/`old` indicator.
|
||||
### 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.
|
||||
@@ -0,0 +1,7 @@
|
||||
# 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
|
||||
@@ -0,0 +1,30 @@
|
||||
# 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.
|
||||
|
||||
## 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
|
||||
- Make sure you have set `GITHUB_TOKEN` and `CIRCLE_API_USER_TOKEN` environment variables in `.envrc.local` file. If you don't have the file, run `cp .envrc.local.example .envrc.local` and edit the file.
|
||||
- To release a new version of `turtle-cli`, run `yarn release` command.
|
||||
- If you wish to release a new *beta* version of `turtle-cli`, run `yarn release:beta` instead.
|
||||
- Update the [changelog](CHANGELOG.md).
|
||||
@@ -0,0 +1,35 @@
|
||||
# Turtle Development
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Working `www` service, see [this README](https://github.com/expo/universe/tree/master/server/www/README.md) for more details.
|
||||
- Own AWS SQS queues. See [this README](https://github.com/expo/universe/tree/master/terraform/turtle-queues/README.md) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
- Run `update-local-secrets` to populate the `.secrets*` files. You'll need to run this any time any secret changes (it shouldn't be very often).
|
||||
- Run `EXPO_UNIVERSE_DIR=/path/to/universe/dir yarn secrets:init-private YOUR_SQS_NICKNAME`. Alternatively, you can create `.secrets.local-queue` file with the SQS queues' urls yourself (`AWS_SQS_OUT_QUEUE_URL`, `AWS_SQS_ANDROID_QUEUE_URL`, `AWS_SQS_ANDROID_PRIORITY_QUEUE_URL`, `AWS_SQS_IOS_QUEUE_URL`, `AWS_SQS_IOS_PRIORITY_QUEUE_URL`)
|
||||
- Run `yarn set-workingdir:local` or `yarn set-workingdir:remote`:
|
||||
- `:local` creates symlinks to the shell apps in `expo` repository (_unfortunately this is currently broken_)
|
||||
- `:remote` downloads precompiled shell apps
|
||||
- Run `yarn` to install node modules.
|
||||
- Run `yarn start:ios` or `yarn start:android` to run Turtle.
|
||||
|
||||
## Updating shell apps
|
||||
|
||||
_TODO_
|
||||
|
||||
## Generating recording files for smoke tests
|
||||
|
||||
Smoke tests are powered by [Nock](https://www.npmjs.com/package/nock) which uses JSON files containing responses to the HTTP requests fired by the build process.
|
||||
|
||||
To record new responses remove old `recording.json` and run tests and then manually schedule a build with `expo-cli` tool.
|
||||
|
||||
As a precaution, the file with HTTP requests/responses contains, among other things, iOS certificates used for the test build, is
|
||||
encrypted with `git-crypt`. Remember not to revoke them, because then the tests will fail.
|
||||
|
||||
## Other notes
|
||||
|
||||
Turtle uses Redis to get notifications (from www) about builds cancellations. To make this feature working, you have to use the same Redis instance as www. Therefore, you need to remember about starting www before starting Turtle. If you forget about it, don't worry, Turtle will remind you to run `yarn start-docker` in `server/www` directory.
|
||||
|
||||
Turtle uploads build artifacts to S3. This could take some time if you have a poor internet connection. To facilitate local development, there is a feature which allows Turtle to fake artifacts upload. `secrets:init-private` script, which you should have run while setting up Turtle, sets fake upload directory to your user's default `Downloads` directory (we're assuming you're using Mac). If you need to test uploading artifacts to S3, you have to edit `.secrets.local` file and comment or remove `TURTLE_FAKE_UPLOAD` and `TURTLE_FAKE_UPLOAD_DIR` environment variables.
|
||||
+19
-114
@@ -1,124 +1,29 @@
|
||||
FROM openjdk:8u141
|
||||
# see docker-base/Dockerfile to learn what's installed in the turtle-android-base image
|
||||
FROM gcr.io/exponentjs/turtle-android-base:0.1.0
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
ADD . /app/turtle
|
||||
|
||||
# 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\
|
||||
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-3859397.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 && \
|
||||
# prevents warnings about missing repo config
|
||||
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/25.0.0/:${PATH}
|
||||
|
||||
RUN yes | sdkmanager --licenses > /dev/null
|
||||
|
||||
# Install Android SDK components
|
||||
RUN sdkmanager \
|
||||
"platform-tools" \
|
||||
"platforms;android-23" \
|
||||
"build-tools;25.0.0" \
|
||||
"extras;android;m2repository" \
|
||||
"extras;google;m2repository"
|
||||
|
||||
# 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
|
||||
|
||||
# Install Gulp
|
||||
RUN npm install -g gulp-cli
|
||||
|
||||
# Install Git
|
||||
RUN echo 'deb http://http.debian.net/debian wheezy-backports main' >> /etc/apt/sources.list && \
|
||||
apt-get update && \
|
||||
apt-get -t wheezy-backports install git-core && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ADD . /app
|
||||
|
||||
RUN for SDK_VERSION in `ls /app/workingdir/android/`; do \
|
||||
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 \
|
||||
; done
|
||||
|
||||
WORKDIR /app
|
||||
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/workingdir/
|
||||
ENV TURTLE_WORKING_DIR_PATH /app/turtle/workingdir/
|
||||
|
||||
CMD ["node", "./build/server.js"]
|
||||
WORKDIR /app/turtle
|
||||
|
||||
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
@@ -0,0 +1,21 @@
|
||||
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,13 +1,43 @@
|
||||
# Turtle CLI
|
||||
<h3 align=center>
|
||||
<img src="logo/horizontal.png" width=50%>
|
||||
</h3>
|
||||
|
||||
Turtle CLI is a command line interface for building Expo standalone apps. You can use it both on your CI and your private computer.
|
||||
[](https://circleci.com/gh/expo/turtle)
|
||||
[](https://npmjs.com/package/turtle-cli)
|
||||
[](https://github.com/expo/turtle/blob/master/LICENSE)
|
||||
|
||||
### Glossary
|
||||
[](http://slack.expo.io)
|
||||
[](https://forums.expo.io/)
|
||||
|
||||
- **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
|
||||
<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](CONTRIBUTING.md)
|
||||
- [Development](DEVELOPMENT.md)
|
||||
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
## 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.
|
||||
@@ -1,6 +1,15 @@
|
||||
#!/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');
|
||||
@@ -0,0 +1,92 @@
|
||||
# If you ever need to rebuild this, run:
|
||||
# yarn docker:build-and-push:android-base-image NEW_IMAGE_SEMVER
|
||||
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\
|
||||
supervisor\
|
||||
--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}
|
||||
|
||||
ADD scripts/android/configureAndroidSdk.sh /tmp/configureAndroidSdk.sh
|
||||
RUN /tmp/configureAndroidSdk.sh --install-all-platforms
|
||||
|
||||
# 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
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const childProcess = require('child_process');
|
||||
const util = require('util');
|
||||
const path = require('path');
|
||||
|
||||
const gulp = require('gulp');
|
||||
const babel = require('gulp-babel');
|
||||
const changed = require('gulp-changed');
|
||||
const nodemon = require('gulp-nodemon');
|
||||
const plumber = require('gulp-plumber');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const ts = require('gulp-typescript');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
const rimrafAsync = util.promisify(rimraf);
|
||||
|
||||
const tsProject = ts.createProject('tsconfig.json');
|
||||
|
||||
gulp.task('clean', async () => {
|
||||
console.log(`Removing build directories...`);
|
||||
await rimrafAsync('build');
|
||||
});
|
||||
|
||||
gulp.task('build:server', () => {
|
||||
console.log(`Compiling the Node.js server JavaScript...`);
|
||||
return tsProject
|
||||
.src()
|
||||
.pipe(plumber())
|
||||
.pipe(changed('build'))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(tsProject())
|
||||
.pipe(babel())
|
||||
.pipe(
|
||||
sourcemaps.write('.', {
|
||||
includeContent: false,
|
||||
sourceRoot: '../src',
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest('build'));
|
||||
});
|
||||
|
||||
gulp.task('watch:source', async () => {
|
||||
console.log(`Watching for changes to the Node.js server JavaScript...`);
|
||||
gulp.watch('src/**/*.(t|j)s', gulp.series('build:server'));
|
||||
});
|
||||
|
||||
gulp.task('watch:local', createWatchTask('development'));
|
||||
gulp.task('watch:server', createWatchTask('production'));
|
||||
|
||||
function createWatchTask(nodeEnv) {
|
||||
return async () => {
|
||||
console.log(`Starting the Node.js server and watching for changes (NODE_ENV=${nodeEnv})...`);
|
||||
// Run nodemon in a separate process to isolate its side effects on stdio streams
|
||||
let nodeCmd = 'node';
|
||||
if (nodeEnv === 'development') {
|
||||
nodeCmd += ' --inspect=:9315';
|
||||
}
|
||||
nodemon({
|
||||
script: './build/server.js',
|
||||
execMap: {
|
||||
js: nodeCmd,
|
||||
},
|
||||
env: {
|
||||
NODE_ENV: nodeEnv,
|
||||
},
|
||||
|
||||
watch: ['./build'],
|
||||
stdout: false,
|
||||
readable: false,
|
||||
}).on('readable', function() {
|
||||
const bunyan = childProcess.fork(
|
||||
path.join('.', 'node_modules', '.bin', 'bunyan'),
|
||||
['-o', 'short', '-l', 'debug', '--color'],
|
||||
{ silent: true }
|
||||
);
|
||||
|
||||
bunyan.stdout.pipe(process.stdout);
|
||||
bunyan.stderr.pipe(process.stderr);
|
||||
this.stdout.pipe(bunyan.stdin);
|
||||
this.stderr.pipe(bunyan.stdin);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
gulp.task(
|
||||
'watch',
|
||||
gulp.series('clean', 'build:server', gulp.parallel('watch:source', 'watch:local'))
|
||||
);
|
||||
|
||||
gulp.task('default', gulp.series('watch'));
|
||||
@@ -9,6 +9,6 @@
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
"testRegex": "(test|spec)\\.ts$",
|
||||
"moduleFileExtensions": ["ts", "js"],
|
||||
"moduleFileExtensions": ["ts", "js", "json"],
|
||||
"verbose": true
|
||||
}
|
||||
@@ -9,6 +9,6 @@
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
"testMatch": [ "**/__smoke__/*.test.ts" ],
|
||||
"moduleFileExtensions": ["ts", "js"],
|
||||
"moduleFileExtensions": ["ts", "js", "json"],
|
||||
"verbose": true
|
||||
}
|
||||
@@ -9,6 +9,6 @@
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
"testMatch": [ "**/__tests__/*.ts" ],
|
||||
"moduleFileExtensions": ["ts", "js"],
|
||||
"moduleFileExtensions": ["ts", "js", "json"],
|
||||
"verbose": true
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"turtle/*": ["src/*"],
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "build"]
|
||||
}
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
environment: ${NAMESPACE}
|
||||
spec:
|
||||
restartPolicy: Always
|
||||
terminationGracePeriodSeconds: 1800 ## wait 30 minutes for any builds to complete
|
||||
terminationGracePeriodSeconds: 1200 ## wait 20 minutes for any builds to complete
|
||||
tolerations:
|
||||
- key: dedicated
|
||||
operator: Equal
|
||||
@@ -50,8 +50,6 @@ spec:
|
||||
value: exp-shell-app-assets
|
||||
- name: AWS_S3_REGION
|
||||
value: us-west-1
|
||||
- name: LOGGLY_SUBDOMAIN
|
||||
value: exponent
|
||||
- name: TURTLE_TEMPORARY_FILES_DIR
|
||||
value: /tmp/turtle
|
||||
# vars from k8s secrets
|
||||
@@ -100,11 +98,6 @@ spec:
|
||||
secretKeyRef:
|
||||
name: turtle-js-config
|
||||
key: aws_cloudwatch_region
|
||||
- name: LOGGLY_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: turtle-js-config
|
||||
key: loggly_token
|
||||
- name: REDIS_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
@@ -135,6 +128,16 @@ spec:
|
||||
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"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
@@ -0,0 +1,228 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
@@ -0,0 +1,5 @@
|
||||
self: super:
|
||||
|
||||
{
|
||||
nodejs = super.nodejs-8_x;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
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
|
||||
''}
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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) ];
|
||||
})
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/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"
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"url": "https://github.com/NixOS/nixpkgs-channels.git",
|
||||
"rev": "80738ed9dc0ce48d7796baed5364eef8072c794d",
|
||||
"date": "2018-11-17T11:18:10+01:00",
|
||||
"sha256": "0anmvr6b47gbbyl9v2fn86mfkcwgpbd5lf0yf3drgm8pbv57c1dc",
|
||||
"fetchSubmodules": false
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"watch": ["src"],
|
||||
"ext": "ts",
|
||||
"ignore": ["src/**/*.test.ts"],
|
||||
"exec": "ts-node -r tsconfig-paths/register --files src/server.ts"
|
||||
}
|
||||
+55
-51
@@ -1,42 +1,43 @@
|
||||
{
|
||||
"name": "turtle-cli",
|
||||
"version": "0.4.3",
|
||||
"version": "0.10.0",
|
||||
"description": "The command-line tool for building standalone Expo apps",
|
||||
"preferGlobal": true,
|
||||
"scripts": {
|
||||
"start": "EXPENV_OVERRIDES=local-common,local expenv gulp",
|
||||
"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",
|
||||
"watch": "EXPENV_OVERRIDES=local-common,local expenv gulp watch:source",
|
||||
"bin:turtle": "./bin/turtle.js",
|
||||
"lint": "eslint src",
|
||||
"prepare": "yarn build",
|
||||
"build": "gulp build:server",
|
||||
"lint": "tslint -c tslint.json 'src/**/*.ts'",
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"prepare": "rimraf ./build && yarn build",
|
||||
"build": "ttsc",
|
||||
"build:production": "./scripts/build.sh",
|
||||
"build:android-tarball:local": "./scripts/android/buildAndroidTarballLocally.sh",
|
||||
"init-workingdir:local": "./scripts/initLocalWorkingdir.sh",
|
||||
"init-workingdir:remote": "yarn init-workingdir:remote-android && yarn init-workingdir:remote-ios",
|
||||
"init-workingdir:remote-android": "./scripts/android/fetchRemoteAndroidTarball.sh",
|
||||
"init-workingdir:remote-ios": "./scripts/ios/fetchRemoteIosTarball.sh",
|
||||
"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",
|
||||
"watch": "ttsc --watch",
|
||||
"secrets:init-private": "./scripts/initPrivateSecrets.sh",
|
||||
"set-workingdir:remote": "./scripts/setWorkingdirMode.sh remote",
|
||||
"set-workingdir:local": "./scripts/setWorkingdirMode.sh local",
|
||||
"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": "yarn test:smoke --testNamePattern=android",
|
||||
"test:smoke:android": "PLATFORM=android yarn test:smoke --testNamePattern=android",
|
||||
"test:smoke:ios": "PLATFORM=ios yarn test:smoke --testNamePattern=iOS",
|
||||
"secrets:init-private": "./scripts/initPrivateSecrets.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:local": "EXPENV_OVERRIDES=local-common,local expenv babel-node scripts/setConfigurations.js",
|
||||
"set-priorities:staging": "expenv babel-node scripts/setConfigurations.js",
|
||||
"set-priorities:production": "EXPENV_OVERRIDES=prod expenv babel-node scripts/setConfigurations.js"
|
||||
"release": "./scripts/release.sh",
|
||||
"release:beta": "./scripts/releaseBeta.sh",
|
||||
"release:update:turtle-cli-example": "./scripts/updateTurtleCliExampleRepo.sh",
|
||||
"docker:build-and-push:android-base-image": "./scripts/android/buildAndPushAndroidBaseImage.sh"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.ts": [
|
||||
"yarn lint:fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"bin": {
|
||||
"turtle": "./bin/turtle.js"
|
||||
@@ -44,7 +45,7 @@
|
||||
"files": [
|
||||
"bin",
|
||||
"build",
|
||||
"scripts/cli",
|
||||
"scripts/android/configureAndroidSdk.sh",
|
||||
"shellTarballs"
|
||||
],
|
||||
"keywords": [
|
||||
@@ -60,68 +61,71 @@
|
||||
"url": "https://github.com/expo/turtle/issues"
|
||||
},
|
||||
"homepage": "https://github.com/expo/turtle#readme",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@expo/babel-preset-cli": "^0.1.3",
|
||||
"@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.109",
|
||||
"@types/lodash": "^4.14.129",
|
||||
"@types/npm-package-arg": "^6.1.0",
|
||||
"@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",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-jest": "^23.6.0",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-universe": "^1.0.7",
|
||||
"eslint-import-resolver-babel-module": "^4.0.0",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-babel": "^7.0.1",
|
||||
"gulp-changed": "^3.2.0",
|
||||
"gulp-nodemon": "^2.4.1",
|
||||
"gulp-plumber": "^1.2.0",
|
||||
"gulp-sourcemaps": "^2.6.4",
|
||||
"gulp-typescript": "^4.0.2",
|
||||
"husky": "^1.3.1",
|
||||
"jest": "^23.6.0",
|
||||
"lint-staged": "^8.1.5",
|
||||
"nock": "^10.0.1",
|
||||
"nodemon": "^1.18.7",
|
||||
"nodemon": "^1.18.11",
|
||||
"release-it": "^12.3.4",
|
||||
"rimraf": "^2.6.2",
|
||||
"source-map-loader": "^0.2.3",
|
||||
"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",
|
||||
"typescript": "^3.0.1"
|
||||
"tslint-eslint-rules": "^5.4.0",
|
||||
"ttypescript": "^1.5.6",
|
||||
"typescript": "^3.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/spawn-async": "^1.4.2",
|
||||
"@expo/xdl": "56.1.4-rc.0",
|
||||
"@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-loggly": "^1.3.4",
|
||||
"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.10",
|
||||
"lodash": "^4.17.11",
|
||||
"progress": "^2.0.0",
|
||||
"raven": "^2.6.2",
|
||||
"request": "^2.88.0",
|
||||
"request-progress": "^3.0.0",
|
||||
"sharp": "^0.21.0",
|
||||
"semver": "^6.0.0",
|
||||
"sharp": "0.22.1",
|
||||
"source-map-support": "^0.5.6",
|
||||
"tar": "^4.4.6",
|
||||
"uuid": "^3.2.1",
|
||||
"which": "^1.3.1",
|
||||
"xdl": "52.0.14-alpha.6+371be041"
|
||||
"which": "^1.3.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@expo/traveling-fastlane-darwin": "1.9.9"
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
|
||||
|
||||
IMAGE_TAG="$1"
|
||||
if [[ -z "$IMAGE_TAG" ]]; then
|
||||
echo "usage: yarn docker:build:android-base-image IMAGE_SEMVER"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE_VERSION_FULL_NAME="gcr.io/exponentjs/turtle-android-base:$IMAGE_TAG"
|
||||
IMAGE_LATEST_FULL_NAME="gcr.io/exponentjs/turtle-android-base:latest"
|
||||
|
||||
pushd $ROOT_DIR > /dev/null
|
||||
echo docker build -f docker-base/Dockerfile -t "$IMAGE_VERSION_FULL_NAME" -t "$IMAGE_LATEST_FULL_NAME" .
|
||||
echo "Successfully built $IMAGE_VERSION_FULL_NAME Docker image"
|
||||
echo gcloud docker -- push "$IMAGE_VERSION_FULL_NAME"
|
||||
echo gcloud docker -- push "$IMAGE_LATEST_FULL_NAME"
|
||||
echo "Successfully pushed $IMAGE_VERSION_FULL_NAME Docker image to GCloud"
|
||||
popd > /dev/null
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xeo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
|
||||
ARTIFACTS_DIR="$ROOT_DIR/artifacts"
|
||||
TEMP_DIR="/tmp/android-shell-app"
|
||||
|
||||
mkdir -p $ARTIFACTS_DIR
|
||||
rm -rf $TEMP_DIR
|
||||
mkdir -p $TEMP_DIR
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/tools-public $TEMP_DIR/tools-public
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/secrets $TEMP_DIR/secrets
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/template-files $TEMP_DIR/template-files
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/android $TEMP_DIR/android
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/package.json $TEMP_DIR/package.json
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/expokit-npm-package $TEMP_DIR/expokit-npm-package
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/exponent/packages $TEMP_DIR/packages
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/libraries/eslint-config-universe $TEMP_DIR/eslint-config-universe
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/libraries/json-file $TEMP_DIR/json-file
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/libraries/osascript $TEMP_DIR/osascript
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/libraries/schemer $TEMP_DIR/schemer
|
||||
ln -s ${EXPO_UNIVERSE_DIR}/package.json $TEMP_DIR/universe-package.json
|
||||
|
||||
# generate dynamic macros
|
||||
mkdir -p $TEMP_DIR/android/expoview/src/main/java/host/exp/exponent/generated/
|
||||
cd $TEMP_DIR/tools-public
|
||||
./generate-dynamic-macros-android.sh
|
||||
rm -rf $TEMP_DIR/secrets
|
||||
|
||||
cd $TEMP_DIR; tar -czhf $ARTIFACTS_DIR/android-shell-builder.tar.gz .
|
||||
rm -rf $TEMP_DIR
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SDKMANAGER=$ANDROID_HOME/tools/bin/sdkmanager
|
||||
|
||||
yes | $SDKMANAGER --licenses > /dev/null
|
||||
if [[ "$1" = "--install-all-platforms" ]]; then
|
||||
yes | $SDKMANAGER \
|
||||
"platforms;android-23" \
|
||||
"platforms;android-24" \
|
||||
"platforms;android-25" \
|
||||
"platforms;android-26" \
|
||||
"platforms;android-27" | grep -v '='; [[ ${PIPESTATUS[1]} = 0 ]]
|
||||
fi
|
||||
yes | $SDKMANAGER "platforms;android-28" | grep -v '='; [[ ${PIPESTATUS[1]} = 0 ]]
|
||||
yes | $SDKMANAGER "platform-tools" | grep -v '='; [[ ${PIPESTATUS[1]} = 0 ]]
|
||||
yes | $SDKMANAGER "build-tools;28.0.3" | grep -v '='; [[ ${PIPESTATUS[1]} = 0 ]]
|
||||
yes | $SDKMANAGER \
|
||||
"extras;android;m2repository" \
|
||||
"extras;google;m2repository" \
|
||||
"extras;google;google_play_services" | grep -v '='; [[ ${PIPESTATUS[1]} = 0 ]]
|
||||
@@ -1,18 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xeo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
|
||||
ARTIFACTS_DIR="$ROOT_DIR/artifacts"
|
||||
WORKING_DIR="$ROOT_DIR/workingdir/android"
|
||||
ANDROID_SHELL_TARBALLS_DIRECTORY="$ROOT_DIR/shellTarballs/android"
|
||||
|
||||
mkdir -p $ARTIFACTS_DIR
|
||||
|
||||
for SDK_VERSION in `ls $ANDROID_SHELL_TARBALLS_DIRECTORY`; do
|
||||
mkdir -p $WORKING_DIR/$SDK_VERSION
|
||||
TARBALL_URI=$(head -n 1 $ANDROID_SHELL_TARBALLS_DIRECTORY/$SDK_VERSION)
|
||||
run expo.s3env --keep AWS_ACCESS_KEY_ID --keep AWS_SECRET_ACCESS_KEY --command retry5 aws s3 cp $TARBALL_URI $ARTIFACTS_DIR/$SDK_VERSION.tar.gz --no-progress
|
||||
tar zxf $ARTIFACTS_DIR/$SDK_VERSION.tar.gz -C $WORKING_DIR/$SDK_VERSION
|
||||
rm -rf $TARBALL_URI $ARTIFACTS_DIR/$SDK_VERSION.tar.gz
|
||||
done
|
||||
$ROOT_DIR/scripts/fetchRemoteTarballs.sh android
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
printf "READY\n"; # signal to superivsord that listener is ready
|
||||
|
||||
while read line; do
|
||||
echo "[supervisord:eventlistener] Processing Event: $line" >&2;
|
||||
kill -SIGQUIT $PPID
|
||||
done < /dev/stdin
|
||||
+8
-1
@@ -2,6 +2,8 @@
|
||||
|
||||
set -xeo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Please specify a platform to build"
|
||||
exit 1
|
||||
@@ -11,7 +13,12 @@ PLATFORM=$1
|
||||
|
||||
yarn
|
||||
yarn run build
|
||||
yarn init-workingdir:remote-$PLATFORM
|
||||
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"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses > /dev/null
|
||||
$ANDROID_HOME/tools/bin/sdkmanager \
|
||||
"platform-tools" \
|
||||
"platforms;android-23" \
|
||||
"build-tools;25.0.0" \
|
||||
"extras;android;m2repository" \
|
||||
"extras;google;m2repository"
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
SCRIPT_NAME=`basename "$0"`
|
||||
DEPLOY_ENDPOINT_URL="https://circleci.com/api/v1.1/project/github/expo/turtle-deploy/tree/master"
|
||||
|
||||
if [[ -z "$1" || -z "$2" ]]; then
|
||||
echo "usage: ${bold}$SCRIPT_NAME PLATFORM ENVIRONMENT [FORCE]${normal}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PLATFORM="$1"
|
||||
ENVIRONMENT="$2"
|
||||
|
||||
if [[ "$3" = "--force" ]]; then
|
||||
FORCE_DEPLOY="true"
|
||||
fi
|
||||
|
||||
if [[ "$PLATFORM" != "android" && "$PLATFORM" != "ios" ]]; then
|
||||
echo "unsupported PLATFORM passed: ${bold}$PLATFORM${normal}"
|
||||
echo "valid values are: ${bold}android${normal}, ${bold}ios${normal}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$ENVIRONMENT" != "staging" && "$ENVIRONMENT" != "production" ]]; then
|
||||
echo "unsupported ENVIRONMENT passed: ${bold}$ENVIRONMENT${normal}"
|
||||
echo "valid values are: ${bold}staging${normal}, ${bold}production${normal}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -z "$CIRCLE_SHA1" ]]; then
|
||||
TURTLE_COMMIT="$CIRCLE_SHA1"
|
||||
elif [[ -z "$FORCE_DEPLOY" ]]; then
|
||||
read -p "You're about to schedule a deploy, are you sure you want to deploy the current commit? (y/n) " -n 1 -r
|
||||
echo # (optional) move to a new line
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "exiting..."
|
||||
exit 0
|
||||
else
|
||||
TURTLE_COMMIT=`git log --pretty=format:%H -1`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$TURTLE_BOT_CIRCLE_API_USER_TOKEN" ]]; then
|
||||
echo "Please set the TURTLE_BOT_CIRCLE_API_USER_TOKEN env variable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $FORCE_DEPLOY = "true" ]]; then
|
||||
curl -X POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-u $TURTLE_BOT_CIRCLE_API_USER_TOKEN: \
|
||||
-d '
|
||||
{
|
||||
"build_parameters": {
|
||||
"CIRCLE_JOB": "deploy_'$PLATFORM'",
|
||||
"TURTLE_ENV": "'$ENVIRONMENT'",
|
||||
"TURTLE_FORCE_DEPLOY": "true"
|
||||
}
|
||||
}' \
|
||||
$DEPLOY_ENDPOINT_URL | jq -r .build_url
|
||||
else
|
||||
curl -X POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-u $TURTLE_BOT_CIRCLE_API_USER_TOKEN: \
|
||||
-d '
|
||||
{
|
||||
"build_parameters": {
|
||||
"CIRCLE_JOB": "deploy_'$PLATFORM'",
|
||||
"TURTLE_ENV": "'$ENVIRONMENT'",
|
||||
"TURTLE_COMMIT": "'$TURTLE_COMMIT'"
|
||||
}
|
||||
}' \
|
||||
$DEPLOY_ENDPOINT_URL | jq -r .build_url
|
||||
fi
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/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
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ensure_link_exists() {
|
||||
if [ ! -L "$2" ]; then
|
||||
ln -s $1 $2
|
||||
echo "$2 link created"
|
||||
fi
|
||||
}
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
|
||||
WORKINGDIR="$ROOT_DIR/workingdir/local"
|
||||
|
||||
if [ ! -d "$WORKINGDIR" ]; then
|
||||
mkdir -p $WORKINGDIR
|
||||
echo "$WORKINGDIR directory created"
|
||||
fi
|
||||
|
||||
LINKS=( "template-files" "package.json" "android" "expokit-npm-package" "packages" "client-builds" "cpp" "exponent-view-template" "ios" "shellAppBase-builds" "shellAppWorkspaces")
|
||||
|
||||
for LINKNAME in ${LINKS[@]}; do
|
||||
ensure_link_exists "$EXPO_UNIVERSE_DIR/exponent/$LINKNAME" "$WORKINGDIR/$LINKNAME"
|
||||
done
|
||||
@@ -1,5 +1,10 @@
|
||||
#!/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
|
||||
@@ -8,16 +13,17 @@ 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`
|
||||
ANDROID_NORMAL=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_android_in | head -1 | cut -d"=" -f2 | xargs`
|
||||
ANDROID_PRIORITY=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_android_in_priority | head -1 | cut -d"=" -f2 | xargs`
|
||||
IOS_NORMAL=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_ios_in | head -1 | cut -d"=" -f2 | xargs`
|
||||
IOS_PRIORITY=`cd $TERRAFORM_DIR; terraform state show module.turtle_queues_local_$1.aws_sqs_queue.jobs_ios_in_priority | 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
|
||||
AWS_SQS_ANDROID_QUEUE_URL="$ANDROID"
|
||||
AWS_SQS_IOS_QUEUE_URL="$IOS"
|
||||
cat << EOF > $TURTLE_DIR/.secrets.local-queue
|
||||
AWS_SQS_ANDROID_QUEUE_URL="$ANDROID_NORMAL"
|
||||
AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="$ANDROID_PRIORITY"
|
||||
AWS_SQS_IOS_QUEUE_URL="$IOS_NORMAL"
|
||||
AWS_SQS_IOS_PRIORITY_QUEUE_URL="$IOS_PRIORITY"
|
||||
AWS_SQS_OUT_QUEUE_URL="$OUT"
|
||||
TURTLE_FAKE_UPLOAD="1"
|
||||
TURTLE_FAKE_UPLOAD_DIR="/Users/$USER/Downloads"
|
||||
TURTLE_WORKING_DIR_PATH="$EXPO_UNIVERSE_DIR/server/turtle/workingdir"
|
||||
TURTLE_USE_LOCAL_WORKING_DIR="1"
|
||||
EOF
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xeo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
|
||||
ARTIFACTS_DIR="$ROOT_DIR/artifacts"
|
||||
WORKING_DIR="$ROOT_DIR/workingdir/ios"
|
||||
IOS_SHELL_TARBALLS_DIRECTORY="$ROOT_DIR/shellTarballs/ios"
|
||||
|
||||
mkdir -p $ARTIFACTS_DIR
|
||||
|
||||
for SDK_VERSION in `ls $IOS_SHELL_TARBALLS_DIRECTORY`; do
|
||||
mkdir -p $WORKING_DIR/$SDK_VERSION
|
||||
TARBALL_URI=$(head -n 1 $IOS_SHELL_TARBALLS_DIRECTORY/$SDK_VERSION)
|
||||
run expo.s3env --keep AWS_ACCESS_KEY_ID --keep AWS_SECRET_ACCESS_KEY --command retry5 aws s3 cp $TARBALL_URI $ARTIFACTS_DIR/$SDK_VERSION.tar.gz --no-progress
|
||||
tar zxf $ARTIFACTS_DIR/$SDK_VERSION.tar.gz -C $WORKING_DIR/$SDK_VERSION
|
||||
rm -rf $TARBALL_URI $ARTIFACTS_DIR/$SDK_VERSION.tar.gz
|
||||
done
|
||||
$ROOT_DIR/scripts/fetchRemoteTarballs.sh ios
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
|
||||
|
||||
if [[ -z "$GITHUB_TOKEN" || -z "$CIRCLE_API_USER_TOKEN" ]]; then
|
||||
yellow=`tput setaf 3`
|
||||
reset=`tput sgr0`
|
||||
echo "${yellow}please set GITHUB_TOKEN and CIRCLE_API_USER_TOKEN env variables in .envrc.local file if you wish to release turtle-cli"
|
||||
echo "run 'cp .envrc.local.example .envrc.local' if you don't have one yet and edit the new file${reset}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$ROOT_DIR/node_modules/.bin/release-it
|
||||
echo
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "!!!! PLEASE REMEMBER TO UPDATE CHANGELOG !!!!"
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/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
|
||||
@@ -1,73 +0,0 @@
|
||||
import { env } from 'turtle/utils/env';
|
||||
import { connect, RedisClient } from 'turtle/utils/redis';
|
||||
import { PLATFORMS } from 'turtle/constants';
|
||||
import {
|
||||
createConfigurationsKey,
|
||||
createDefaultConfigurationKey,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
} from 'turtle/utils/priorities';
|
||||
|
||||
const TIMEOUT = 3000;
|
||||
|
||||
// Turtle before doing anything (and after every build) checks for the first config
|
||||
// (an element in config table with key=i) that is not taken (config.i is null/outdated)
|
||||
// or is taken by this process itself.
|
||||
// If Turtle dies unexpectedly the configuration will become free after TTL expires,
|
||||
// so the state (number of HP/NP turtles) should come back to normal soon.
|
||||
|
||||
// For example, if a configuration table looks like this:
|
||||
// [ HIGH_CONFIGURATION, NORMAL_CONFIGURATION, HIGH_CONFIGURATION ]
|
||||
// If there is one turtle it runs with High Priority first.
|
||||
// If there are two turtles, one runs with High Priority first, the second one with Normal Priority first.
|
||||
// If the first dies, and the third is started in his place, it gets 3rd config (again HP-first),
|
||||
// but after some time, because of TTL for config reservations,
|
||||
// they should come back to using configurations no. 1 and 2.
|
||||
// If there are no more available configurations from the table, the default configuration is used.
|
||||
|
||||
|
||||
const AVAILABLE_CONFIGURATIONS_IOS = [
|
||||
HIGH_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
];
|
||||
|
||||
const AVAILABLE_CONFIGURATIONS_ANDROID = [
|
||||
HIGH_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
HIGH_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
NORMAL_CONFIGURATION,
|
||||
];
|
||||
|
||||
|
||||
const DEFAULT_CONFIGURATION = HIGH_CONFIGURATION;
|
||||
|
||||
async function run() {
|
||||
const redis = await connect(TIMEOUT, RedisClient.Configuration);
|
||||
|
||||
await redis.set(createConfigurationsKey(PLATFORMS.IOS), JSON.stringify(AVAILABLE_CONFIGURATIONS_IOS));
|
||||
await redis.set(createConfigurationsKey(PLATFORMS.ANDROID), JSON.stringify(AVAILABLE_CONFIGURATIONS_ANDROID));
|
||||
await redis.set(createDefaultConfigurationKey(PLATFORMS.IOS), JSON.stringify(DEFAULT_CONFIGURATION));
|
||||
await redis.set(createDefaultConfigurationKey(PLATFORMS.ANDROID), JSON.stringify(DEFAULT_CONFIGURATION));
|
||||
|
||||
redis.disconnect();
|
||||
}
|
||||
|
||||
run()
|
||||
.then(() => console.log('All done'))
|
||||
.catch(err => console.error('Error:', err));
|
||||
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/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 the .secrets.local-queue file yourself with AWS_SQS_ANDROID_QUEUE_URL, AWS_SQS_ANDROID_PRIORITY_QUEUE_URL, AWS_SQS_IOS_QUEUE_URL, AWS_SQS_IOS_PRIORITY_QUEUE_URL and AWS_SQS_OUT_QUEUE_URL variables."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# @dsokal: this is currently broken
|
||||
#
|
||||
# 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
|
||||
echo "Setting local workingdir is currently broken, sorry :("
|
||||
exit -1
|
||||
elif [ "$1" == "remote" ]; then
|
||||
setup_remote
|
||||
switch_remote
|
||||
else
|
||||
echo "You need to pass remote or local as argument"
|
||||
exit -1
|
||||
fi
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ENVIRONMENT=${1:-production}
|
||||
|
||||
govc vm.ip -wait 5s turtle-js-"${ENVIRONMENT}"-*
|
||||
@@ -1,34 +1,26 @@
|
||||
#!/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_IOS_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_staging_ios_in.fifo"
|
||||
export AWS_SQS_IOS_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_staging_ios_in.fifo"
|
||||
export AWS_SQS_ANDROID_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_staging_android_in.fifo"
|
||||
export AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_staging_android_in.fifo"
|
||||
export AWS_SQS_OUT_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_staging_out.fifo"
|
||||
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="localhost"
|
||||
export API_PORT="3000"
|
||||
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
|
||||
smoke_result=$?
|
||||
|
||||
yarn test:unit
|
||||
unit_result=$?
|
||||
|
||||
[[ $smoke_result != 0 || $unit_result != 0 ]] && \
|
||||
echo && \
|
||||
echo "Tests failed." && \
|
||||
exit -1
|
||||
|
||||
exit 0
|
||||
@@ -1,13 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ueo pipefail
|
||||
|
||||
export NODE_ENV=test
|
||||
|
||||
export ENVIRONMENT="development"
|
||||
export AWS_SQS_IOS_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_jakub_ios_in.fifo"
|
||||
export AWS_SQS_ANDROID_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_jakub_android_in.fifo"
|
||||
export AWS_SQS_IOS_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_jakub_ios_in_priority.fifo"
|
||||
export AWS_SQS_ANDROID_PRIORITY_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_jakub_android_in_priority.fifo"
|
||||
export AWS_SQS_OUT_QUEUE_URL="https://sqs.us-west-2.amazonaws.com/274251141632/turtle_jobs_local_jakub_out.fifo"
|
||||
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"
|
||||
@@ -17,18 +19,9 @@ export API_HOSTNAME="staging.expo.io"
|
||||
export API_PORT="443"
|
||||
export REDIS_URL="noop"
|
||||
export REDIS_CONFIG_URL="noop"
|
||||
export DATADOG_DISABLED="true"
|
||||
|
||||
yarn init-workingdir:remote-ios
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../.. && pwd )"
|
||||
SDK_VERSION=sdk32 $ROOT_DIR/scripts/ios/fetchRemoteIosTarball.sh
|
||||
|
||||
yarn test:smoke:ios
|
||||
smoke_result=$?
|
||||
|
||||
yarn test:unit
|
||||
unit_result=$?
|
||||
|
||||
[[ $smoke_result != 0 || $unit_result != 0 ]] && \
|
||||
echo && \
|
||||
echo "Tests failed." && \
|
||||
exit -1
|
||||
|
||||
exit 0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ueo pipefail
|
||||
|
||||
export NODE_ENV=test
|
||||
|
||||
export ENVIRONMENT="development"
|
||||
@@ -19,8 +21,6 @@ export API_HOSTNAME="noop"
|
||||
export API_PORT="443"
|
||||
export REDIS_URL="noop"
|
||||
export REDIS_CONFIG_URL="noop"
|
||||
export DATADOG_DISABLED="true"
|
||||
|
||||
yarn test:unit
|
||||
unit_result=$?
|
||||
|
||||
exit $unit_result
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
DEPLOY_ENDPOINT_URL="https://circleci.com/api/v1.1/project/github/expo/turtle-cli-example/tree/updates-do-not-remove-me"
|
||||
|
||||
curl -X POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-u $CIRCLE_API_USER_TOKEN: \
|
||||
-d '
|
||||
{
|
||||
"build_parameters": {
|
||||
"CIRCLE_JOB": "update",
|
||||
"TURTLE_TAG": "latest"
|
||||
}
|
||||
}' \
|
||||
$DEPLOY_ENDPOINT_URL 2>/dev/null | jq -r .build_url
|
||||
@@ -1 +0,0 @@
|
||||
s3://exp-artifacts/android-shell-builder-67bd02667e29221707f8c1dd11e739eada25ef55.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-67bd02667e29221707f8c1dd11e739eada25ef55.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-67bd02667e29221707f8c1dd11e739eada25ef55.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-67bd02667e29221707f8c1dd11e739eada25ef55.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-67bd02667e29221707f8c1dd11e739eada25ef55.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-c19ce0d88a153f481fd790e23bdcd6f2d5ea7fd6.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-5c339ff7bab6f2161d378cc70e1bf04d32ad98dd.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-89b2d24c86737d5a489c6a18467e31b2f9ce9005.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-55e2cc952dc8bae3ebba8aaaab6eb1199ac7b0d0.tar.gz
|
||||
s3://exp-artifacts/android-shell-builder-f796aaffa0b5715079b2950faf26c2ff4e53e4c0.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-aebd669d6573b0b3c802871d94cdb8b4116678d2.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
s3://exp-artifacts/android-shell-builder-d1aabbbe9d124201bf453fa985c36324ae4b76fb.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
s3://exp-artifacts/ios-expo-client-5b74b634263fa1980d88cdd9b7d8f16b06c36671.tar.gz
|
||||
@@ -1 +0,0 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-26-db356a09877642d64023af98e4e2e1e632fbe4df.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-30-7d017a96d00fbf18ee7e5581ea47528b9cc78afd.tar.gz
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-30-6863276e6b9605e31228c845a047387571959e9b.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-56824ecea6ba10f5a9d8991545a1c47ee3284f5f.tar.gz
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-55848298c7332f7586c4281fa691a4ca31548532.tar.gz
|
||||
@@ -1 +1 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-e3855783ed0618f4dcf326dc353c6e2951e05c49.tar.gz
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-edd02214dd84368c197df32a2d30a901d6c766ff.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-7a0e6bb94bd3edb2bc2dc501d6c09ad6edccd1bb.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
s3://exp-artifacts/ios-shell-builder-sdk-latest-7c4c6866646398874a092769299036e8d22e8d49.tar.gz
|
||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -3,14 +3,13 @@ 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';
|
||||
import { PLATFORMS } from 'turtle/constants';
|
||||
|
||||
|
||||
jest.mock('../builders/utils/uploader.ts', () => ({
|
||||
uploadBuildToS3: jest.fn(() => {
|
||||
console.log('Faking uploading build');
|
||||
logger.debug('Faking uploading build');
|
||||
return 'legit_path';
|
||||
}),
|
||||
}));
|
||||
@@ -68,11 +67,11 @@ function mockFinish() {
|
||||
.post('/', (body: any) => {
|
||||
const keys = Object.keys(body);
|
||||
if (keys.includes('MessageBody')) {
|
||||
const mb = JSON.parse(body['MessageBody']);
|
||||
const mb = JSON.parse(body.MessageBody);
|
||||
if (mb.status === 'finished') {
|
||||
return true;
|
||||
} else if (mb.status === 'errored') {
|
||||
fail('Build ended with error')
|
||||
fail('Build ended with error');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -13,3 +13,28 @@ export const TYPE_DIMENSIONS = (type: string) => [
|
||||
{ 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 },
|
||||
],
|
||||
];
|
||||
+30
-24
@@ -1,16 +1,22 @@
|
||||
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';
|
||||
import calculateStatistics from 'turtle/aws/cloudwatch/statistics';
|
||||
import { EXTRA_DIMENSIONS, GROUP_HASH } from 'turtle/aws/cloudwatch/constants';
|
||||
import { Metric, MetricData, MetricConfiguration, MetricRegistrationObject, MetricsChunk } from 'turtle/aws/cloudwatch/types';
|
||||
|
||||
interface State {
|
||||
metrics: Array<Metric>;
|
||||
interface IState {
|
||||
metrics: IMetric[];
|
||||
registeredMetrics: {
|
||||
[key: string]: MetricConfiguration;
|
||||
[key: string]: IMetricConfiguration;
|
||||
};
|
||||
intervalId: NodeJS.Timer | null;
|
||||
}
|
||||
@@ -19,7 +25,7 @@ const SUCCESS_SUFFIX = '.success';
|
||||
const FAIL_SUFFIX = '.fail';
|
||||
const CHUNK_SIZE = 20;
|
||||
|
||||
const state: State = {
|
||||
const state: IState = {
|
||||
metrics: [],
|
||||
registeredMetrics: {},
|
||||
intervalId: null,
|
||||
@@ -46,7 +52,7 @@ export function addMetricData({
|
||||
success = true,
|
||||
explicitName = false,
|
||||
extraDimensions = [],
|
||||
}: MetricData) {
|
||||
}: IMetricData) {
|
||||
if (config.cloudwatch.disabled) {
|
||||
return;
|
||||
}
|
||||
@@ -57,7 +63,7 @@ export function addMetricData({
|
||||
return;
|
||||
}
|
||||
const { unit } = registeredMetric;
|
||||
const metric: Metric = {
|
||||
const metric: IMetric = {
|
||||
MetricName: metricName,
|
||||
Unit: unit,
|
||||
Value: value,
|
||||
@@ -114,7 +120,7 @@ function _dumpMetrics() {
|
||||
logger.trace(
|
||||
'[cloudwatch] lenghts for state.metrics=%d, state.registeredMetrics=%d',
|
||||
state.metrics.length,
|
||||
Object.keys(state.registeredMetrics).length
|
||||
Object.keys(state.registeredMetrics).length,
|
||||
);
|
||||
|
||||
_addEmptyMetrics(state.metrics);
|
||||
@@ -124,7 +130,7 @@ function _dumpMetrics() {
|
||||
state.metrics = [];
|
||||
}
|
||||
|
||||
function _addEmptyMetrics(metrics: Array<Metric>) {
|
||||
function _addEmptyMetrics(metrics: IMetric[]) {
|
||||
const seenMetrics = metrics.reduce((acc, i) => {
|
||||
if (!acc.has(i.MetricName)) {
|
||||
acc.add(i.MetricName);
|
||||
@@ -134,46 +140,46 @@ function _addEmptyMetrics(metrics: Array<Metric>) {
|
||||
|
||||
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 }));
|
||||
toAdd.forEach((name) => addMetricData({ name, value: 0, explicitName: true }));
|
||||
}
|
||||
|
||||
function _formatMetrics(metrics: Array<Metric>) {
|
||||
function _formatMetrics(metrics: IMetric[]) {
|
||||
const reducedMetrics = _reduceMetrics(metrics);
|
||||
const metricsWithDimensions = reducedMetrics.map(metric => {
|
||||
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 }));
|
||||
return joinedDimensions.map((i) => Object.assign({}, metric, { Dimensions: i }));
|
||||
});
|
||||
const metricData = _.flatten(metricsWithDimensions);
|
||||
const chunks = _.chunk(metricData, CHUNK_SIZE);
|
||||
return chunks.map(chunk => ({
|
||||
return chunks.map((chunk) => ({
|
||||
Namespace: config.cloudwatch.namespace,
|
||||
MetricData: chunk,
|
||||
}));
|
||||
}
|
||||
|
||||
function _reduceMetrics(metrics: Array<Metric>) {
|
||||
function _reduceMetrics(metrics: IMetric[]) {
|
||||
const grouped = _.groupBy(metrics, GROUP_HASH);
|
||||
return _.reduce(
|
||||
grouped,
|
||||
(acc: Array<Metric>, val: any) => {
|
||||
const { MetricName: key } = val[0] as Metric;
|
||||
(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: Array<MetricsChunk>) {
|
||||
function _pushMetrics(metrics: IMetricsChunk[]) {
|
||||
logger.trace('[cloudwatch] pushing metrics', JSON.stringify(metrics, null, '\t'));
|
||||
metrics.forEach(metricsChunk => {
|
||||
cloudWatch.putMetricData(metricsChunk, err => {
|
||||
metrics.forEach((metricsChunk) => {
|
||||
cloudWatch.putMetricData(metricsChunk, (err) => {
|
||||
if (err) {
|
||||
logger.warn('[cloudwatch]', err);
|
||||
logger.warn({ err }, '[cloudwatch]');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Metric } from 'turtle/aws/cloudwatch/types';
|
||||
import { IMetric } from 'turtle/aws/cloudwatch/types';
|
||||
|
||||
export function sum(metrics: Array<Metric>) {
|
||||
export function sum(metrics: IMetric[]) {
|
||||
if (metrics.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const reduced = metrics.reduce((acc: Metric | null, i: Metric) => {
|
||||
const reduced = metrics.reduce((acc: IMetric | null, i: IMetric) => {
|
||||
let result = acc;
|
||||
if (!result) {
|
||||
result = {...i};
|
||||
result = { ...i };
|
||||
} else {
|
||||
result.Value += i.Value;
|
||||
}
|
||||
@@ -16,12 +16,12 @@ export function sum(metrics: Array<Metric>) {
|
||||
return [reduced];
|
||||
}
|
||||
|
||||
export function avg(metrics: Array<Metric>) {
|
||||
export function avg(metrics: IMetric[]) {
|
||||
if (!metrics.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const metric = sum(metrics)[0] as Metric;
|
||||
const metric = sum(metrics)[0] as IMetric;
|
||||
metric.Value = metric.Value / metrics.length;
|
||||
return [metric];
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Metric, MetricWithStats } from 'turtle/aws/cloudwatch/types';
|
||||
import { IMetric, MetricWithStats } from 'turtle/aws/cloudwatch/types';
|
||||
|
||||
export default function calculateStatistics(metrics: Array<Metric>) {
|
||||
export default function calculateStatistics(metrics: IMetric[]) {
|
||||
if (!metrics.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const reduced = metrics.reduce((acc: MetricWithStats | null, i: Metric) => {
|
||||
const reduced = metrics.reduce((acc: MetricWithStats | null, i: IMetric) => {
|
||||
let result = acc;
|
||||
if (!result) {
|
||||
result = Object.assign({}, i, {
|
||||
|
||||
+12
-12
@@ -1,6 +1,6 @@
|
||||
import { EXTRA_DIMENSIONS, GROUP_HASH } from 'turtle/aws/cloudwatch/constants';
|
||||
|
||||
export interface Metric {
|
||||
export interface IMetric {
|
||||
MetricName: string;
|
||||
Unit: string;
|
||||
Value: number;
|
||||
@@ -11,8 +11,8 @@ export interface Metric {
|
||||
SampleCount: number;
|
||||
Sum: number;
|
||||
};
|
||||
[EXTRA_DIMENSIONS]: any,
|
||||
[GROUP_HASH]: string,
|
||||
[EXTRA_DIMENSIONS]: any;
|
||||
[GROUP_HASH]: string;
|
||||
}
|
||||
|
||||
export type MetricWithStats = {
|
||||
@@ -21,10 +21,10 @@ export type MetricWithStats = {
|
||||
Minimum: number;
|
||||
SampleCount: number;
|
||||
Sum: number;
|
||||
}
|
||||
} & Metric;
|
||||
},
|
||||
} & IMetric;
|
||||
|
||||
export interface MetricData {
|
||||
export interface IMetricData {
|
||||
name: string;
|
||||
value: number;
|
||||
success?: boolean;
|
||||
@@ -32,17 +32,17 @@ export interface MetricData {
|
||||
extraDimensions?: any;
|
||||
}
|
||||
|
||||
export interface MetricConfiguration {
|
||||
export interface IMetricConfiguration {
|
||||
unit: string;
|
||||
statistics?: boolean;
|
||||
reducer?: any;
|
||||
addEmpty?: boolean;
|
||||
dimensions?: any;
|
||||
};
|
||||
}
|
||||
|
||||
export type MetricRegistrationObject = { metricName: string, explicitName?: boolean } & MetricConfiguration;
|
||||
export type MetricRegistrationObject = { metricName: string, explicitName?: boolean } & IMetricConfiguration;
|
||||
|
||||
export interface MetricsChunk {
|
||||
export interface IMetricsChunk {
|
||||
Namespace: string;
|
||||
MetricData: Array<Metric>;
|
||||
};
|
||||
MetricData: IMetric[];
|
||||
}
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import AWS from 'aws-sdk';
|
||||
import _ from 'lodash';
|
||||
import fs from 'fs-extra';
|
||||
import _ from 'lodash';
|
||||
|
||||
import config from 'turtle/config';
|
||||
|
||||
interface FileUploadParams {
|
||||
interface IFileUploadParams {
|
||||
bucketName?: string;
|
||||
key: string;
|
||||
srcPath: string;
|
||||
@@ -17,7 +17,7 @@ const s3 = new AWS.S3({
|
||||
|
||||
export default s3;
|
||||
|
||||
export async function uploadFile({ bucketName = config.s3.bucket, key, srcPath }: FileUploadParams) {
|
||||
export async function uploadFile({ bucketName = config.s3.bucket, key, srcPath }: IFileUploadParams) {
|
||||
return await s3
|
||||
.upload({
|
||||
Bucket: bucketName,
|
||||
|
||||
+8
-8
@@ -2,11 +2,11 @@ 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';
|
||||
import { QUEUE_URL, OUTPUT_QUEUE_URL } from 'turtle/aws/utils';
|
||||
|
||||
const sqs = new AWS.SQS({
|
||||
apiVersion: '2012-11-05',
|
||||
@@ -26,7 +26,7 @@ export async function receiveMessage(priority: string) {
|
||||
return sqs
|
||||
.receiveMessage(params)
|
||||
.promise()
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
if (data.Messages) {
|
||||
logger.info(`Received a message`);
|
||||
return data.Messages[0];
|
||||
@@ -35,8 +35,8 @@ export async function receiveMessage(priority: string) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error('Receive error', err);
|
||||
.catch((err) => {
|
||||
logger.error({ err }, 'Receive error');
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
@@ -62,13 +62,13 @@ export async function changeMessageVisibility(priority: string, receiptHandle: s
|
||||
}
|
||||
|
||||
// Every VISIBILITY_TIMEOUT_SEC / 3 seconds we are telling AWS SQS
|
||||
// that we're still proccessing the message, so it does not
|
||||
// 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('Error at change msg visibility', err);
|
||||
changeMessageVisibility(priority, receiptHandle).catch((err) => {
|
||||
logger.warn({ err }, 'Error at change msg visibility');
|
||||
});
|
||||
}
|
||||
}, (VISIBILITY_TIMEOUT_SEC * 1000) / 3);
|
||||
@@ -86,6 +86,6 @@ export async function sendMessage(jobId: string, status: JOB_UPDATE_TYPE, data =
|
||||
return await sqs.sendMessage(params).promise();
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error(`Error sending SQS message: ${JSON.stringify(params)}}`, err);
|
||||
logger.error({ err }, `Error sending SQS message: ${JSON.stringify(params)}}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export class ErrorWithCommandHelp extends Error {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export class ErrorWithProgramHelp extends Error {
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import _ from 'lodash';
|
||||
import fs from 'fs-extra';
|
||||
import uuid from 'uuid';
|
||||
import _ from 'lodash';
|
||||
|
||||
import builder from 'turtle/builders/android';
|
||||
import { ErrorWithCommandHelp } from 'turtle/bin/commands/errors';
|
||||
import { PLATFORMS } from 'turtle/constants';
|
||||
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]');
|
||||
@@ -14,39 +13,38 @@ export default (program: any, setCommonCommandOptions: any) => {
|
||||
.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)'
|
||||
'path to your Keystore (please provide Keystore password and Key password as EXPO_ANDROID_KEYSTORE_PASSWORD'
|
||||
+ ' and EXPO_ANDROID_KEY_PASSWORD env variables)',
|
||||
)
|
||||
.option('--keystore-alias <alias>', 'keystore Alias')
|
||||
.option(
|
||||
'-t --type <build>',
|
||||
'type of build: app-bundle|apk',
|
||||
/^(app-bundle|apk)$/i,
|
||||
'app-bundle',
|
||||
)
|
||||
.option(
|
||||
'-m --mode <build>',
|
||||
'type of build: debug|release',
|
||||
/^(debug|release)$/i,
|
||||
'release',
|
||||
)
|
||||
.description(
|
||||
'Build a standalone APK for your project, signed and ready for submission to the Google Play Store.'
|
||||
'Build a standalone APK or App Bundle for your project, either signed and ready for submission to'
|
||||
+ ' the Google Play Store or in debug mode.',
|
||||
)
|
||||
.asyncAction(
|
||||
createBuilderAction({
|
||||
program,
|
||||
command,
|
||||
prepareCredentials,
|
||||
buildJobObject,
|
||||
builder,
|
||||
platform: PLATFORMS.ANDROID,
|
||||
os: ['darwin', 'linux'],
|
||||
})
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const buildJobObject = (appJSON: any, { releaseChannel, username, projectDir, publicUrl }: any, credentials: any) => ({
|
||||
config: {
|
||||
..._.get(appJSON, 'expo.android.config', {}),
|
||||
releaseChannel,
|
||||
publicUrl,
|
||||
},
|
||||
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;
|
||||
@@ -57,7 +55,7 @@ const prepareCredentials = async (cmd: any) => {
|
||||
if (!credentialsExist) {
|
||||
if (someCredentialsExist) {
|
||||
throw new ErrorWithCommandHelp(
|
||||
'Please provide all required credentials - Keystore (with password), Keystore alias and Key password'
|
||||
'Please provide all required credentials - Keystore (with password), Keystore alias and Key password',
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { default as buildIOS } from 'turtle/bin/commands/build/ios';
|
||||
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) => {
|
||||
@@ -15,15 +15,16 @@ function setCommonCommandOptions(cmd: any) {
|
||||
.option('-o --output <output-file-path>', 'output file path')
|
||||
.option(
|
||||
'--public-url <url>',
|
||||
'the URL of an externally hosted manifest (for self-hosted apps).'
|
||||
'the URL of an externally hosted manifest (for self-hosted apps).',
|
||||
)
|
||||
.option(
|
||||
'--release-channel <channel-name>',
|
||||
'pull from specified release channel (default: default)'
|
||||
);
|
||||
'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),
|
||||
}
|
||||
};
|
||||
@@ -1,11 +1,10 @@
|
||||
import _ from 'lodash';
|
||||
import uuid from 'uuid';
|
||||
import fs from 'fs-extra';
|
||||
import _ from 'lodash';
|
||||
|
||||
import builder from 'turtle/builders/ios';
|
||||
import { ErrorWithCommandHelp } from 'turtle/bin/commands/errors';
|
||||
import { IOS, PLATFORMS } from 'turtle/constants';
|
||||
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]');
|
||||
@@ -16,47 +15,31 @@ export default (program: any, setCommonCommandOptions: any) => {
|
||||
'-t --type <build>',
|
||||
'type of build: archive|simulator',
|
||||
/^(archive|simulator)$/i,
|
||||
'archive'
|
||||
'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)'
|
||||
'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.'
|
||||
'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) {
|
||||
if (cmd.type !== IOS_BUILD_TYPES.ARCHIVE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -68,7 +51,8 @@ const prepareCredentials = async (cmd: any) => {
|
||||
|
||||
if (!credentialsExist) {
|
||||
throw new ErrorWithCommandHelp(
|
||||
'Please provide all required credentials - Apple Team ID, Distribution Certificate P12 (with password) and Provisioning Profile'
|
||||
'Please provide all required credentials'
|
||||
+ '- Apple Team ID, Distribution Certificate P12 (with password) and Provisioning Profile',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export class ErrorWithProgramHelp extends Error {}
|
||||
export class ErrorWithCommandHelp extends Error {}
|
||||
@@ -1,11 +1,12 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
import logger from 'turtle/logger';
|
||||
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
|
||||
import { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';
|
||||
import setup from 'turtle/bin/setup/setup';
|
||||
import { ErrorWithCommandHelp, ErrorWithProgramHelp } from 'turtle/bin/commands/errors';
|
||||
import { PLATFORMS } from 'turtle/constants';
|
||||
import logger from 'turtle/logger';
|
||||
|
||||
const l = logger.withFields({ buildPhase: 'setting up environment' });
|
||||
const l = logger.child({ buildPhase: 'setting up environment' });
|
||||
|
||||
function createSetupCommand(platform: string, os?: string) {
|
||||
return (program: any) => {
|
||||
@@ -16,7 +17,7 @@ function createSetupCommand(platform: string, os?: string) {
|
||||
.description(`Setup environment for building ${_.capitalize(platform)} standalone apps.`)
|
||||
.option(
|
||||
'--sdk-version <sdk-version>',
|
||||
'version of Expo SDK shell app to download (optional)'
|
||||
'version of Expo SDK shell app to download (optional)',
|
||||
)
|
||||
.asyncAction(async (cmd: any) => await setupAction(program, cmd, platform, os));
|
||||
};
|
||||
@@ -30,10 +31,9 @@ async function setupAction(program: any, cmd: any, platform: string, os?: string
|
||||
|
||||
const { sdkVersion } = cmd;
|
||||
await setup(platform, sdkVersion);
|
||||
l.info('it\'s all set!')
|
||||
l.info('it\'s all set!');
|
||||
} catch (err) {
|
||||
logger.error(`Failed to setup environment for ${platform} builds`);
|
||||
logger.error(err.stack);
|
||||
logger.error({ err }, `Failed to setup environment for ${platform} builds`);
|
||||
if (err instanceof ErrorWithCommandHelp) {
|
||||
cmd.help();
|
||||
} else if (err instanceof ErrorWithProgramHelp) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
@@ -16,8 +16,8 @@ const resolveEnv = () => {
|
||||
};
|
||||
|
||||
const currentEnv = resolveEnv();
|
||||
const isLocal = (env: string) => env === 'local';
|
||||
const isStaging = (env: string) => env === 'staging';
|
||||
const isLocal = (envName: string) => envName === 'local';
|
||||
const isStaging = (envName: string) => envName === 'staging';
|
||||
|
||||
const apiConfig = {
|
||||
protocol: 'https',
|
||||
|
||||
+19
-15
@@ -1,11 +1,13 @@
|
||||
import { LoggerDetach, ModuleVersion } from 'xdl';
|
||||
import path from 'path';
|
||||
|
||||
import { LoggerDetach, ModuleVersion } from '@expo/xdl';
|
||||
import program, { Command } from 'commander';
|
||||
import _ from 'lodash';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import logger from 'turtle/logger';
|
||||
import * as commands from 'turtle/bin/commands';
|
||||
import logger from 'turtle/logger';
|
||||
|
||||
const { name, version } = require('../../package.json');
|
||||
const { name, version } = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
|
||||
|
||||
const ModuleVersionChecker = ModuleVersion.createModuleVersionChecker(name, version);
|
||||
|
||||
@@ -15,36 +17,38 @@ Command.prototype.asyncAction = function asyncAction(asyncFn: (...asyncFnArgs: a
|
||||
return this.action(async (...args) => {
|
||||
try {
|
||||
await checkForUpdateAsync();
|
||||
} catch (e) {}
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'Failed to check for turtle-cli update.');
|
||||
}
|
||||
return await asyncFn(...args);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function run(programName: string) {
|
||||
runAsync(programName).catch(e => {
|
||||
logger.error('Uncaught Error', e);
|
||||
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));
|
||||
Object.values(commands).forEach((command) => registerCommand(program, command));
|
||||
program.parse(process.argv);
|
||||
|
||||
const subCommand = process.argv[2];
|
||||
if (subCommand) {
|
||||
const commands = program.commands.reduce((acc: Array<string>, command: any) => {
|
||||
acc.push(command['_name']);
|
||||
const alias = command['_alias'];
|
||||
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 (!_.includes(commands, subCommand)) {
|
||||
if (!commandNames.includes(subCommand)) {
|
||||
logger.error(
|
||||
`"${subCommand}" is not an ${programName} command. See "${programName} --help" for the full list of commands.`
|
||||
`"${subCommand}" is not an ${programName} command. See "${programName} --help" for the full list of commands.`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -60,7 +64,7 @@ async function checkForUpdateAsync() {
|
||||
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`
|
||||
Run \`npm install -g ${name}\` to get the latest version`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 178 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user