Compare commits

...
Author SHA1 Message Date
Quinlan Jung ca3a118d43 debug msg 2019-07-01 14:21:37 -07:00
Quinlan Jung 1fca07d58b schema change 2019-07-01 14:21:36 -07:00
Quinlan Jung 30274bfd7e [turtle] use provisioiningProfileId if specified (#88)
* [turtle] use provisioiningProfileId if specified

* make ts happy

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

* Update CHANGELOG.md

* Apply suggestions from code review

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

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

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

* Update CHANGELOG.md

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

* Update scripts/android/supervisordEventListener.sh

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

* Update CHANGELOG.md

Co-Authored-By: Dominik Sokal <[email protected]>
2019-06-12 13:21:53 +02:00
Dominik Sokal 05b96a5b6f update builders configuration to the current state 2019-06-12 09:55:44 +02:00
Dominik Sokal 5467aca0fb update CHANGELOG 2019-06-11 17:55:17 +02:00
Dominik Sokal cf1e1daa26 Release 0.8.2 2019-06-11 17:54:15 +02:00
Dominik Sokal 8649968531 turtle-cli fixes for sdk 33 (#90)
* fix setting up android shell app (sdk 33)

* don't fail turtle-cli if manifest is falsy

* updated CHANGELOG
2019-06-11 17:53:32 +02:00
29 changed files with 497 additions and 702 deletions

No files matched your search

+31 -2
View File
@@ -5,8 +5,37 @@ 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]
### Added
- Adhoc Builds: use provisioningProfileId if specified.
- Registering supported SDK versions in Redis.
## [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
@@ -18,7 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Turtle CLI logo to the project (created by [@zularizal](https://github.com/zularizal))!
- Shell apps for SDK 33.
- Support for Android App Bundles.
- Support for Android App Bundles (App bundles are built by default, use `-t apk` to build apk).
### Changed
- Updated Android shell app for SDK 32 to fix AppAuth issue (https://github.com/expo/expo/pull/4115) and to fix a newer than expected JSC version.
- Default value for build timeout to 15 minutes.
@@ -100,7 +129,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.5.10] - 2019-02-19
### Added
- Register Turtle version in Redis.
- Registering Turtle version in Redis.
### Changed
- Update Android shell app for SDK 32 to fix [update](https://github.com/expo/expo/issues/3504) and [back button](https://github.com/expo/expo/issues/1786) issues.
+6 -15
View File
@@ -24,6 +24,7 @@ RUN dpkg --add-architecture i386 && \
unzip\
yarn\
zlib1g:i386\
supervisor\
--no-install-recommends && \
apt-get clean
@@ -51,20 +52,8 @@ ENV PATH ${ANDROID_HOME}/tools:${PATH}
ENV PATH ${ANDROID_HOME}/tools/bin:${PATH}
ENV PATH ${ANDROID_HOME}/build-tools/28.0.3/:${PATH}
RUN yes | sdkmanager --licenses > /dev/null
RUN yes | sdkmanager \
"platforms;android-23" \
"platforms;android-24" \
"platforms;android-25" \
"platforms;android-26" \
"platforms;android-27" \
"platforms;android-28" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager "platform-tools" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager "build-tools;28.0.3" | grep -v '=' || echo 'no output'
RUN yes | sdkmanager \
"extras;android;m2repository" \
"extras;google;m2repository" \
"extras;google;google_play_services" | grep -v '=' || echo 'no output'
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
@@ -123,4 +112,6 @@ ENV TURTLE_WORKING_DIR_PATH /app/turtle/workingdir/
WORKDIR /app/turtle
CMD ["node", "./build/server.js"]
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "turtle-cli",
"version": "0.8.1",
"version": "0.8.6",
"description": "The command-line tool for building standalone Expo apps",
"preferGlobal": true,
"scripts": {
@@ -13,6 +13,7 @@
"prepare": "rimraf ./build && yarn build",
"build": "ttsc",
"build:production": "./scripts/build.sh",
"watch": "ttsc --watch",
"secrets:init-private": "./scripts/initPrivateSecrets.sh",
"set-workingdir:remote": "./scripts/setWorkingdirMode.sh remote",
"set-workingdir:local": "./scripts/setWorkingdirMode.sh local",
@@ -59,7 +60,7 @@
"files": [
"bin",
"build",
"scripts/cli",
"scripts/android/configureAndroidSdk.sh",
"shellTarballs"
],
"keywords": [
@@ -110,7 +111,7 @@
},
"dependencies": {
"@expo/spawn-async": "^1.4.2",
"@expo/xdl": "54.1.4",
"@expo/xdl": "55.0.7",
"@google-cloud/logging-bunyan": "^0.9.5",
"async-retry": "^1.2.1",
"aws-sdk": "^2.226.1",
@@ -131,7 +132,7 @@
"request": "^2.88.0",
"request-progress": "^3.0.0",
"semver": "^6.0.0",
"sharp": "^0.21.0",
"sharp": "0.22.1",
"source-map-support": "^0.5.6",
"tar": "^4.4.6",
"uuid": "^3.2.1",
+20
View File
@@ -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 ]]
+8
View File
@@ -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
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
SDKMANAGER=$ANDROID_HOME/tools/bin/sdkmanager
yes | $SDKMANAGER --licenses > /dev/null
yes | $SDKMANAGER "platforms;android-28"
yes | $SDKMANAGER "platform-tools"
yes | $SDKMANAGER "build-tools;28.0.3"
yes | $SDKMANAGER \
"extras;android;m2repository" \
"extras;google;m2repository" \
"extras;google;google_play_services"
+1 -1
View File
@@ -1 +1 @@
s3://exp-artifacts/android-shell-builder-5d51dcbeaabfcc29d6aa9f268719d10ca7cfe6b0.tar.gz
s3://exp-artifacts/android-shell-builder-5090aab941f92c912c6643a1e25cc69f9f67d8e6.tar.gz
+8 -24
View File
@@ -1,6 +1,5 @@
import fs from 'fs-extra';
import _ from 'lodash';
import uuid from 'uuid';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { createBuilderAction } from 'turtle/bin/utils/builder';
@@ -24,16 +23,21 @@ export default (program: any, setCommonCommandOptions: any) => {
/^(app-bundle|apk)$/i,
'app-bundle',
)
.option(
'-m --mode <build>',
'type of build: debug|release',
/^(debug|release)$/i,
'release',
)
.description(
'Build a standalone APK or App Bundle for your project, 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'],
@@ -41,26 +45,6 @@ export default (program: any, setCommonCommandOptions: any) => {
);
};
const buildJobObject = (
appJSON: any,
{ releaseChannel, username, projectDir, publicUrl, buildType }: any,
credentials: any,
) => ({
config: {
..._.get(appJSON, 'expo.android.config', {}),
releaseChannel,
androidPackage: _.get(appJSON, 'expo.android.package'),
publicUrl,
buildType,
},
id: uuid.v4(),
platform: PLATFORMS.ANDROID,
sdkVersion: _.get(appJSON, 'expo.sdkVersion'),
projectDir,
experienceName: `@${username}/${_.get(appJSON, 'expo.slug')}`,
...(credentials && { credentials }),
});
const prepareCredentials = async (cmd: any) => {
const { keystorePath, keystoreAlias } = cmd;
const keystorePassword = process.env.EXPO_ANDROID_KEYSTORE_PASSWORD;
-17
View File
@@ -1,6 +1,5 @@
import fs from 'fs-extra';
import _ from 'lodash';
import uuid from 'uuid';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { createBuilderAction } from 'turtle/bin/utils/builder';
@@ -32,7 +31,6 @@ export default (program: any, setCommonCommandOptions: any) => {
program,
command,
prepareCredentials,
buildJobObject,
builder,
platform: PLATFORMS.IOS,
os: 'darwin',
@@ -40,21 +38,6 @@ export default (program: any, setCommonCommandOptions: any) => {
);
};
const buildJobObject = (appJSON: any, { releaseChannel, buildType, username, publicUrl }: any, credentials: any) => ({
config: {
..._.get(appJSON, 'expo.ios.config', {}),
buildType,
releaseChannel,
bundleIdentifier: _.get(appJSON, 'expo.ios.bundleIdentifier'),
publicUrl,
},
id: uuid.v4(),
platform: PLATFORMS.IOS,
sdkVersion: _.get(appJSON, 'expo.sdkVersion'),
experienceName: `@${username}/${_.get(appJSON, 'expo.slug')}`,
...(credentials && { credentials }),
});
const prepareCredentials = async (cmd: any) => {
if (cmd.type !== IOS_BUILD_TYPES.ARCHIVE) {
return null;
+6 -8
View File
@@ -20,10 +20,6 @@ const REQUIRED_TOOLS: IToolDefinition[] = [
command: 'bash',
missingDescription: 'Please install bash',
},
{
command: 'gulp',
missingDescription: 'Run `npm install -g gulp-cli` (or `yarn global add gulp-cli`) to install gulp',
},
{
command: 'javac',
missingDescription: 'Please install JDK (version 8 or newer) - check https://jdk.java.net/',
@@ -67,7 +63,7 @@ function formatShellAppTarballUriPath(sdkMajorVersion: string) {
return path.join(config.directories.shellTarballsDir, PLATFORMS.ANDROID, `sdk${sdkMajorVersion}`);
}
async function _shellAppPostDownloadAction(workingdir: string) {
async function _shellAppPostDownloadAction(sdkVersion: string, workingdir: string) {
const inWorkingdir = (filename: string) => path.join(workingdir, filename);
if (await fs.pathExists(inWorkingdir('universe-package.json'))) {
@@ -82,9 +78,11 @@ async function _shellAppPostDownloadAction(workingdir: string) {
await _installNodeModules(workingdir);
}
// TODO: remove following lines after upgrading android shell app
const toolsPublicDir = path.join(workingdir, 'tools-public');
await _installNodeModules(toolsPublicDir);
// TODO: remove this after making sure that we don't need node_modules in tools-public for older sdks
if (ExponentTools.parseSdkMajorVersion(sdkVersion) < 33) {
const toolsPublicDir = path.join(workingdir, 'tools-public');
await _installNodeModules(toolsPublicDir);
}
}
async function _installNodeModules(cwd: string) {
+4 -2
View File
@@ -4,7 +4,7 @@ import path from 'path';
import decompress from 'decompress';
import fs from 'fs-extra';
import { formatArtifactDownloadPath } from 'turtle/bin/setup/utils/common';
import * as utils from 'turtle/bin/setup/utils/common';
import download from 'turtle/bin/setup/utils/downloader';
import config from 'turtle/config';
import logger from 'turtle/logger';
@@ -16,9 +16,10 @@ const l = logger.child(LOGGER_FIELDS);
export default async function ensureAndroidNDKIsPresent() {
const androidNdkDir = path.join(config.directories.androidDependenciesDir, 'ndk');
await utils.removeDirectoryUnlessReady(androidNdkDir);
if (!(await fs.pathExists(androidNdkDir))) {
await fs.ensureDir(androidNdkDir);
const androidNdkDownloadPath = formatArtifactDownloadPath(ANDROID_NDK_URL);
const androidNdkDownloadPath = utils.formatArtifactDownloadPath(ANDROID_NDK_URL);
try {
l.info('Downloading Android NDK');
@@ -26,6 +27,7 @@ export default async function ensureAndroidNDKIsPresent() {
await download(ANDROID_NDK_URL, androidNdkDownloadPath);
l.info('Decompressing Android NDK');
await decompress(androidNdkDownloadPath, androidNdkDir, { strip: 1 });
await utils.markDirectoryAsReady(androidNdkDir);
l.info('Android NDK installed successfully');
} catch (err) {
await fs.remove(androidNdkDir);
+5 -3
View File
@@ -5,7 +5,7 @@ import { ExponentTools } from '@expo/xdl';
import decompress from 'decompress';
import fs from 'fs-extra';
import { formatArtifactDownloadPath } from 'turtle/bin/setup/utils/common';
import * as utils from 'turtle/bin/setup/utils/common';
import download from 'turtle/bin/setup/utils/downloader';
import config from 'turtle/config';
import logger from 'turtle/logger';
@@ -17,9 +17,10 @@ const l = logger.child(LOGGER_FIELDS);
export default async function ensureAndroidSDKIsPresent() {
const androidSdkDir = path.join(config.directories.androidDependenciesDir, 'sdk');
await utils.removeDirectoryUnlessReady(androidSdkDir);
if (!(await fs.pathExists(androidSdkDir))) {
await fs.ensureDir(androidSdkDir);
const androidSdkDownloadPath = formatArtifactDownloadPath(ANDROID_SDK_URL);
const androidSdkDownloadPath = utils.formatArtifactDownloadPath(ANDROID_SDK_URL);
try {
l.info('Downloading Android SDK');
@@ -31,6 +32,7 @@ export default async function ensureAndroidSDKIsPresent() {
await fs.remove(androidSdkDownloadPath);
l.info('Configuring Android SDK, this may take a while');
await _configureSdk(androidSdkDir);
await utils.markDirectoryAsReady(androidSdkDir);
l.info('Android SDK installed and configured successfully');
} catch (err) {
await fs.remove(androidSdkDir);
@@ -52,7 +54,7 @@ async function _configureSdk(androidSdkDir: string) {
await ExponentTools.spawnAsyncThrowError('./configureAndroidSdk.sh', [], {
pipeToLogger: true,
loggerFields: LOGGER_FIELDS,
cwd: path.join(config.directories.rootDir, 'scripts/cli'),
cwd: path.join(config.directories.rootDir, 'scripts/android'),
env: {
...process.env,
ANDROID_HOME: androidSdkDir,
+33 -2
View File
@@ -17,7 +17,7 @@ interface IShellAppFormaters {
formatShellAppTarballUriPath: (sdkMajorVersion: string) => string;
}
type PostDownloadAction = (workingdir: string) => void;
type PostDownloadAction = (sdkVersion: string, workingdir: string) => void;
export async function checkSystem(requiredTools: IToolDefinition[]) {
await ensureToolsAreInstalled(requiredTools);
@@ -29,14 +29,17 @@ export async function ensureShellAppIsPresent(
postDownloadAction?: PostDownloadAction,
) {
const workingdir = formatters.formatShellAppDirectory({ sdkVersion });
const shellAppMetadata = await _readShellAppTarballS3Uri(sdkVersion, formatters);
await removeDirectoryUnlessReady(workingdir, shellAppMetadata);
if (await fs.pathExists(workingdir)) {
return;
}
l.info(`shell app for SDK ${sdkVersion} doesn't exist, downloading...`);
await _downloadShellApp(sdkVersion, workingdir, formatters);
if (postDownloadAction) {
await postDownloadAction(workingdir);
await postDownloadAction(sdkVersion, workingdir);
}
await markDirectoryAsReady(workingdir, shellAppMetadata);
}
async function _downloadShellApp(sdkVersion: string, targetDirectory: string, formatters: IShellAppFormaters) {
@@ -65,3 +68,31 @@ async function _readShellAppTarballS3Uri(sdkVersion: string, formatters: IShellA
const data = await fs.readFile(filePath, 'utf8');
return data.trim();
}
export async function removeDirectoryUnlessReady(dir: string, metadata?: string) {
const readyFilePath = path.join(dir, '.ready');
const readyFileExists = await fs.pathExists(readyFilePath);
let shouldRemove = false;
if (readyFileExists) {
if (metadata !== undefined) {
const readyFileContents = (await fs.readFile(readyFilePath, 'utf-8')).trim();
if (readyFileContents !== metadata) {
shouldRemove = true;
}
}
} else {
shouldRemove = true;
}
if (shouldRemove) {
await fs.remove(dir);
}
}
export async function markDirectoryAsReady(dir: string, metadata?: string) {
const readyFilePath = path.join(dir, '.ready');
if (metadata === undefined) {
await fs.open(readyFilePath, 'w');
} else {
await fs.writeFile(readyFilePath, metadata);
}
}
+40 -2
View File
@@ -1,10 +1,13 @@
import { ExponentTools } from '@expo/xdl';
import _ from 'lodash';
import uuid from 'uuid';
import { ErrorWithCommandHelp } from 'turtle/bin/commands/ErrorWithCommandHelp';
import { ErrorWithProgramHelp } from 'turtle/bin/commands/ErrorWithProgramHelp';
import setup from 'turtle/bin/setup/setup';
import * as ProjectUtils from 'turtle/bin/utils/project';
import * as UserUtils from 'turtle/bin/utils/user';
import { getExperienceUrl } from 'turtle/builders/utils/common';
import logger from 'turtle/logger';
import { sanitizeJob } from 'turtle/validator';
@@ -12,7 +15,6 @@ export function createBuilderAction({
program,
command,
prepareCredentials,
buildJobObject,
builder,
platform,
os,
@@ -55,6 +57,7 @@ export function createBuilderAction({
const args = {
releaseChannel: cmd.releaseChannel || 'default',
buildType: cmd.type,
buildMode: cmd.mode,
username: userData.username || 'anonymous',
projectDir: ProjectUtils.resolveAbsoluteDir(projectDirArg),
publicUrl: cmd.publicUrl,
@@ -65,7 +68,7 @@ export function createBuilderAction({
await setup(platform, sdkVersion);
const credentials = await prepareCredentials(cmd);
const rawJob = {
...buildJobObject(appJSON, args, credentials),
...await buildJobObject(platform, appJSON, args, credentials),
...cmd.buildDir && { fakeUploadDir: ProjectUtils.resolveAbsoluteDir(cmd.buildDir) },
...cmd.output && { fakeUploadBuildPath: ProjectUtils.resolveAbsoluteDir(cmd.output) },
};
@@ -82,3 +85,38 @@ export function createBuilderAction({
}
};
}
const buildJobObject = async (
platform: 'android' | 'ios',
appJSON: any,
{ releaseChannel, buildType, buildMode, username, publicUrl, projectDir }: any,
credentials: any,
) => {
const job = {
config: {
..._.get(appJSON, 'expo.ios.config', {}),
buildType,
...(platform === 'android' ? { buildMode } : {}),
releaseChannel,
...(platform === 'ios' ? { bundleIdentifier: _.get(appJSON, 'expo.ios.bundleIdentifier') } : {}),
...(platform === 'android' ? { androidPackage: _.get(appJSON, 'expo.android.package') } : {}),
publicUrl,
},
id: uuid.v4(),
platform,
projectDir,
sdkVersion: _.get(appJSON, 'expo.sdkVersion'),
experienceName: `@${username}/${_.get(appJSON, 'expo.slug')}`,
...(credentials && { credentials }),
};
const url = getExperienceUrl(job.experienceName, job.config.publicUrl);
const manifest = await ExponentTools.getManifestAsync(url, {
'Exponent-SDK-Version': _.get(appJSON, 'expo.sdkVersion'),
'Exponent-Platform': platform,
'Expo-Release-Channel': releaseChannel,
'Accept': 'application/expo+json,application/json',
});
return { ...job, manifest };
};
+3 -2
View File
@@ -75,12 +75,12 @@ async function runShellAppBuilder(
logger.info({ buildPhase: 'resolve native modules' }, 'Resolving universal modules dependencies');
const enabledModules = semver.satisfies(sdkVersion, '>= 33.0.0')
? await resolveNativeModules(workingDir, manifest.dependencies)
? await resolveNativeModules(workingDir, _.get(manifest, 'dependencies'))
: null;
try {
await AndroidShellApp.createAndroidShellAppAsync({
url: commonUtils.getExperienceUrl(jobData),
url: commonUtils.getExperienceUrl(jobData.experienceName, jobData.config.publicUrl),
sdkVersion,
keystore: tempKeystorePath,
manifest,
@@ -93,6 +93,7 @@ async function runShellAppBuilder(
outputFile: outputFilePath,
modules: enabledModules,
buildType: jobData.config.buildType,
buildMode: jobData.config.buildMode,
});
} catch (err) {
commonUtils.logErrorOnce(err);
+1 -5
View File
@@ -1,13 +1,9 @@
import * as url from 'url';
import config from 'turtle/config';
import { IJob } from 'turtle/job';
import logger from 'turtle/logger';
export function getExperienceUrl(job: IJob) {
const { experienceName, config: jobConfig } = job;
const { publicUrl } = jobConfig;
export function getExperienceUrl(experienceName: string, publicUrl?: string) {
// publicUrl is passed in if user wants to build an externally hosted app
if (publicUrl) {
return publicUrl;
+20 -12
View File
@@ -3,7 +3,6 @@ import path from 'path';
import spawnAsync from '@expo/spawn-async';
import { IosCodeSigning } from '@expo/xdl';
import fs from 'fs-extra';
import isEmpty from 'lodash/isEmpty';
import * as sqs from 'turtle/aws/sqs';
import BuildError, { BuildErrorReason } from 'turtle/builders/BuildError';
@@ -21,10 +20,18 @@ async function prepareAdHocBuildCredentials(job: IJob) {
}
const { bundleIdentifier } = job.config;
const { certP12, certPassword, teamId, appleSession, udids } = job.credentials;
const {
certP12,
certPassword,
teamId,
appleSession,
udids,
provisioningProfileId,
} = job.credentials;
const certSerialNumber = IosCodeSigning.findP12CertSerialNumber(certP12, certPassword);
const args = [
...(provisioningProfileId ? ['--profile-id', provisioningProfileId] : []),
teamId,
udids!.join(','),
bundleIdentifier,
@@ -32,25 +39,26 @@ async function prepareAdHocBuildCredentials(job: IJob) {
];
try {
if (provisioningProfileId) {
logger.info(
`Using ad hoc provisioning profile id: ${provisioningProfileId}`,
);
}
const credentials = await runFastlaneAction(
travelingFastlane.manageAdHocProvisioningProfile,
args,
{ env: { FASTLANE_SESSION: appleSession } },
);
if (isEmpty(credentials)) {
if (!job.credentials.provisioningProfile) {
// a user has generated the provisioning profile for his app, but he probably deleted it from Expo servers, ...
throw new BuildError(
BuildErrorReason.PROVISIONING_PROFILE_MISSING,
`Provisioning profile is missing on Expo servers.`,
);
}
return;
}
logger.info('New ad hoc provisioning profile successfully created');
job.credentials.provisioningProfile = credentials.provisioningProfile;
if (!credentials.provisioningProfileUpdateTimestamp) {
// dont need to persist profile because nothing changed
return;
}
if (isOffline()) {
const provisioningProfilePath = path.join(job.projectDir, `adhoc.mobileprovision`);
await fs.writeFile(provisioningProfilePath, Buffer.from(credentials.provisioningProfile, 'base64'));
+1 -1
View File
@@ -43,7 +43,7 @@ export default async function runShellAppBuilder(ctx: IContext, job: IJob): Prom
});
} else {
Object.assign(shellAppParams, {
url: commonUtils.getExperienceUrl(job),
url: commonUtils.getExperienceUrl(job.experienceName, job.config.publicUrl),
releaseChannel,
sdkVersion,
});
+17 -11
View File
@@ -5,26 +5,32 @@ import path from 'path';
import config from 'turtle/config';
import { IJob } from 'turtle/job';
let SUPPORTED_SDK_VERSIONS: number[];
interface IVersionsMap {
[platform: string]: number[];
}
const versions: IVersionsMap = {};
export async function ensureCanBuildSdkVersion(job: IJob) {
if (config.builder.useLocalWorkingDir) {
return;
}
if (!SUPPORTED_SDK_VERSIONS) {
SUPPORTED_SDK_VERSIONS = await findSupportedSdkVersions(job.platform);
}
const platformVersions = await findSupportedSdkVersions(job.platform);
const targetMajorSdkVersion = ExponentTools.parseSdkMajorVersion(job.sdkVersion || job.manifest.sdkVersion);
if (!SUPPORTED_SDK_VERSIONS.includes(targetMajorSdkVersion)) {
if (!platformVersions.includes(targetMajorSdkVersion)) {
throw new Error(`Unsupported SDK Version!`);
}
}
async function findSupportedSdkVersions(platform: 'android' | 'ios'): Promise<number[]> {
const SDK_DIR_PREFIX = 'sdk';
const files = await fs.readdir(path.join(config.directories.workingDir, platform));
const sdks = files.filter((file) => file.startsWith(SDK_DIR_PREFIX));
return sdks.map((sdk) => parseInt(sdk.substr(SDK_DIR_PREFIX.length), 10));
export async function findSupportedSdkVersions(platform: 'android' | 'ios'): Promise<number[]> {
if (versions[platform]) {
return versions[platform];
} else {
const SDK_DIR_PREFIX = 'sdk';
const files = await fs.readdir(path.join(config.directories.workingDir, platform));
const sdks = files.filter((file) => file.startsWith(SDK_DIR_PREFIX));
versions[platform] = sdks.map((sdk) => parseInt(sdk.substr(SDK_DIR_PREFIX.length), 10));
return versions[platform];
}
}
+5
View File
@@ -16,4 +16,9 @@ export enum ANDROID_BUILD_TYPES {
APP_BUNDLE = 'app-bundle',
}
export enum ANDROID_BUILD_MODES {
DEBUG = 'debug',
RELEASE = 'release',
}
export { BUILD };
+3 -1
View File
@@ -1,4 +1,4 @@
import { ANDROID_BUILD_TYPES, IOS_BUILD_TYPES } from 'turtle/constants';
import { ANDROID_BUILD_MODES, ANDROID_BUILD_TYPES, IOS_BUILD_TYPES } from 'turtle/constants';
export interface IJob {
platform: 'android' | 'ios';
@@ -14,6 +14,7 @@ export interface IJob {
bundleIdentifier?: string;
// android
androidPackage?: string;
buildMode?: ANDROID_BUILD_MODES;
};
credentials: {
// android
@@ -25,6 +26,7 @@ export interface IJob {
certP12?: string;
certPassword?: string;
provisioningProfile?: string;
provisioningProfileId?: string;
teamId?: string;
appleSession?: string;
udids?: string[];
+4 -1
View File
@@ -64,7 +64,10 @@ async function processJob(jobData: any) {
setCurrentJobId(job.id);
const pingerHandle = sqs.changeMessageVisibilityRecurring(priority, jobData.ReceiptHandle, job.id);
logger.info(`Doing job MessageId=${jobData.MessageId} BuildId=${job.id} ${Date.now()}`);
logger.info(
`Doing job MessageId=${jobData.MessageId} BuildId=${job.id} `
+ `Priority=${priority.slice(0, priority.length - 8)} ${Date.now()}`,
);
const cancelled = await redis.checkIfCancelled(job.id);
if (cancelled) {
+5 -1
View File
@@ -1,6 +1,6 @@
import Joi from 'joi';
import { PLATFORMS } from 'turtle/constants';
import { ANDROID_BUILD_MODES, ANDROID_BUILD_TYPES, PLATFORMS } from 'turtle/constants';
import baseJobSchema from 'turtle/jobsSchemas/base';
export default baseJobSchema.concat(
@@ -12,5 +12,9 @@ export default baseJobSchema.concat(
keystoreAlias: Joi.string(),
keystore: Joi.string(),
}),
config: Joi.object().keys({
buildMode: Joi.string().valid(Object.values(ANDROID_BUILD_MODES)).default(ANDROID_BUILD_MODES.RELEASE),
buildType: Joi.string().valid(Object.values(ANDROID_BUILD_TYPES)).default(ANDROID_BUILD_TYPES.APK),
}),
}),
);
+1
View File
@@ -17,6 +17,7 @@ export default baseJobSchema.concat(
teamId: Joi.string().required(),
// it's not required for adhoc Expo Client builds
provisioningProfile: Joi.string(),
provisioningProfileId: Joi.string(),
appleSession: Joi.string(),
udids: Joi.array().items(Joi.string()),
})
+1
View File
@@ -17,6 +17,7 @@ class Logger {
name: 'turtle',
level: config.logger.level,
platform: config.platform,
serializers: bunyan.stdSerializers,
...config.deploymentEnv && { environment: config.deploymentEnv },
streams: Object.values(streams),
});
+7 -7
View File
@@ -43,13 +43,13 @@ const AVAILABLE_CONFIGURATIONS_ANDROID = [
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_ONLY_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
HIGH_CONFIGURATION,
+9 -4
View File
@@ -1,13 +1,15 @@
import { LoggerDetach } from '@expo/xdl';
import { findSupportedSdkVersions } from 'turtle/builders/utils/version';
import config from 'turtle/config';
import { doJob } from 'turtle/jobManager';
import logger from 'turtle/logger';
import setup from 'turtle/setup';
import { checkShouldExit, setShouldExit, turtleVersion } from 'turtle/turtleContext';
import { getRedisClient, RedisClient } from 'turtle/utils/redis';
import { getRedisClient } from 'turtle/utils/redis';
const REDIS_TURTLE_VERSION_KEY = 'turtle:version';
const REDIS_TURTLE_SUPPORTED_SDK_VERSIONS_KEY = `turtle:${config.platform}:sdkVersions`;
process.on('unhandledRejection', (err) => logger.error({ err }, 'Unhandled promise rejection'));
@@ -35,11 +37,14 @@ async function main() {
}
try {
const redis = await getRedisClient(RedisClient.Configuration);
const redis = await getRedisClient();
await redis.set(REDIS_TURTLE_VERSION_KEY, turtleVersion);
logger.info(`Register Turtle version ${turtleVersion} in Redis`);
logger.info(`Registered Turtle version (${turtleVersion}) in Redis`);
const sdkVersions = (await findSupportedSdkVersions(config.platform)).join(',');
await redis.set(REDIS_TURTLE_SUPPORTED_SDK_VERSIONS_KEY, sdkVersions);
logger.info(`Registered supported SDK versions (${sdkVersions}) in Redis`);
} catch (err) {
logger.error({ err }, 'Failed to register Turtle version in Redis');
logger.error({ err }, 'Failed to set versions in Redis');
}
while (true) {
+17
View File
@@ -0,0 +1,17 @@
[supervisord]
nodaemon=true
[program:turtle]
directory=/app/turtle
command=node ./build/server.js
autorestart=true
startretries=5
startsecs=600
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[eventlistener:turtle_failure]
events=PROCESS_STATE_FATAL
command=/app/turtle/scripts/android/supervisordEventListener.sh
+236 -565
View File
File diff suppressed because it is too large. Load diff