mirror of
https://github.com/expo/turtle.git
synced 2026-11-14 19:12:55 -10:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f432f453f | ||
|
|
44b2b0a9be | ||
|
|
30789e939e | ||
|
|
60a12f6710 | ||
|
|
838f628ddd |
No files matched your search
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [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).
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "turtle-cli",
|
||||
"version": "0.6.1",
|
||||
"version": "0.7.0",
|
||||
"description": "The command-line tool for building standalone Expo apps",
|
||||
"preferGlobal": true,
|
||||
"scripts": {
|
||||
@@ -130,7 +130,7 @@
|
||||
"tar": "^4.4.6",
|
||||
"uuid": "^3.2.1",
|
||||
"which": "^1.3.1",
|
||||
"xdl": "53.5.3"
|
||||
"xdl": "53.5.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@expo/traveling-fastlane-darwin": "^1.8.1"
|
||||
|
||||
@@ -36,7 +36,7 @@ setup_local() {
|
||||
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")
|
||||
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"
|
||||
@@ -55,6 +55,14 @@ setup_remote() {
|
||||
$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
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
switch_local() {
|
||||
|
||||
@@ -2,6 +2,7 @@ import path from 'path';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import _ from 'lodash';
|
||||
import semver from 'semver';
|
||||
import uuidv4 from 'uuid/v4';
|
||||
import { AndroidShellApp, ImageUtils } from 'xdl';
|
||||
|
||||
@@ -9,6 +10,7 @@ import getOrCreateCredentials from 'turtle/builders/utils/android/credentials';
|
||||
import { formatShellAppDirectory } from 'turtle/builders/utils/android/workingdir';
|
||||
import * as commonUtils from 'turtle/builders/utils/common';
|
||||
import * as imageHelpers from 'turtle/builders/utils/image';
|
||||
import { resolveNativeModules } from 'turtle/builders/utils/unimodules';
|
||||
import { uploadBuildToS3 } from 'turtle/builders/utils/uploader';
|
||||
import { ensureCanBuildSdkVersion } from 'turtle/builders/utils/version';
|
||||
import config from 'turtle/config';
|
||||
@@ -66,6 +68,11 @@ async function runShellAppBuilder(
|
||||
const sdkVersion = _.get(manifest, 'sdkVersion', sdkVersionFromJob);
|
||||
const workingDir = formatShellAppDirectory({ sdkVersion });
|
||||
|
||||
logger.info({ buildPhase: 'resolve native modules' }, 'Resolving universal modules dependencies');
|
||||
const enabledModules = semver.satisfies(sdkVersion, '>= 33.0.0')
|
||||
? await resolveNativeModules(workingDir, manifest.dependencies)
|
||||
: null;
|
||||
|
||||
try {
|
||||
await AndroidShellApp.createAndroidShellAppAsync({
|
||||
url: commonUtils.getExperienceUrl(jobData),
|
||||
@@ -79,6 +86,7 @@ async function runShellAppBuilder(
|
||||
releaseChannel: jobConfig.releaseChannel,
|
||||
workingDir,
|
||||
outputFile: outputFilePath,
|
||||
modules: enabledModules,
|
||||
});
|
||||
} catch (err) {
|
||||
commonUtils.logErrorOnce(err);
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
import fs from 'fs-extra';
|
||||
import filter from 'lodash/filter';
|
||||
import keys from 'lodash/keys';
|
||||
import merge from 'lodash/merge';
|
||||
import values from 'lodash/values';
|
||||
import path from 'path';
|
||||
import logger from 'turtle/logger';
|
||||
|
||||
export interface IUnimoduleEntry {
|
||||
name: string;
|
||||
version: string;
|
||||
dirname: string;
|
||||
}
|
||||
|
||||
interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
dirname: string; // could be different than name
|
||||
dependencies: string[];
|
||||
}
|
||||
|
||||
export async function resolveNativeModules(workingdir: string, packages?: string[]): Promise<IUnimoduleEntry[]> {
|
||||
const resolver = new Resolver(workingdir);
|
||||
await resolver.init();
|
||||
|
||||
if (!packages) {
|
||||
resolver.addAll();
|
||||
} else {
|
||||
const corePackages = await readCorePackages(workingdir);
|
||||
for (const pkg of corePackages) {
|
||||
if (resolver.isUnimodule(pkg)) {
|
||||
resolver.addModule(pkg);
|
||||
}
|
||||
}
|
||||
for (const pkg of packages) {
|
||||
if (resolver.isUnimodule(pkg)) {
|
||||
resolver.addModule(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resolver.getModules();
|
||||
}
|
||||
|
||||
async function readCorePackages(workingdir: string) {
|
||||
const pkgJsonPath = path.join(workingdir, 'node_modules', 'react-native-unimodules', 'package.json');
|
||||
if (await fs.pathExists(pkgJsonPath)) {
|
||||
const packageJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));
|
||||
return keys(packageJson.dependencies);
|
||||
} else {
|
||||
logger.warn('No core packages detected');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
interface IDependencyInfo {
|
||||
[key: string]: IPackageInfo;
|
||||
}
|
||||
|
||||
class Resolver {
|
||||
private workingdir: string;
|
||||
private modulesMap: {[key: string]: IUnimoduleEntry};
|
||||
private dependencyMap: IDependencyInfo;
|
||||
|
||||
constructor(workingdir: string) {
|
||||
this.workingdir = workingdir;
|
||||
this.modulesMap = {};
|
||||
this.dependencyMap = {};
|
||||
}
|
||||
|
||||
public async init() {
|
||||
this.dependencyMap = await generateDependenciesInfo(this.workingdir);
|
||||
}
|
||||
|
||||
public isUnimodule(moduleName: string): boolean {
|
||||
return !!this.dependencyMap[moduleName];
|
||||
}
|
||||
|
||||
public addAll() {
|
||||
for (const moduleName of Object.keys(this.dependencyMap)) {
|
||||
this.addModule(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
public addModule(moduleName: string) {
|
||||
if (this.dependencyMap[moduleName]) {
|
||||
this.resolveModule(moduleName);
|
||||
} else {
|
||||
throw new Error('Attempting to add unknown module');
|
||||
}
|
||||
}
|
||||
|
||||
public getModules(): IUnimoduleEntry[] {
|
||||
return values(this.modulesMap);
|
||||
}
|
||||
|
||||
private async resolveModule(moduleName: string) {
|
||||
if (this.modulesMap[moduleName]) {
|
||||
return;
|
||||
}
|
||||
const pkg = this.dependencyMap[moduleName];
|
||||
logger.info(`Adding ${moduleName}:${pkg.version}`);
|
||||
this.modulesMap[moduleName] = {
|
||||
name: pkg.name,
|
||||
dirname: pkg.dirname,
|
||||
version: pkg.version,
|
||||
};
|
||||
for (const dep of pkg.dependencies) {
|
||||
this.resolveModule(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function generateDependenciesInfo(workingdir: string): Promise<IDependencyInfo> {
|
||||
const dir = await fs.readdir(path.join(workingdir, 'packages'));
|
||||
const map: IDependencyInfo = {};
|
||||
|
||||
// scrap directory for package metadata
|
||||
for (const pkgName of dir) {
|
||||
const pkg = await getPackage(workingdir, pkgName);
|
||||
if (pkg) {
|
||||
map[pkg.name] = pkg;
|
||||
}
|
||||
}
|
||||
|
||||
// handle @unimodules directory
|
||||
const unimodulesDir = await fs.readdir(path.join(workingdir, 'packages', '@unimodules'));
|
||||
for (const pkgName of unimodulesDir) {
|
||||
const pkg = await getPackage(workingdir, path.join('@unimodules', pkgName));
|
||||
if (pkg) {
|
||||
map[pkg.name] = pkg;
|
||||
}
|
||||
}
|
||||
|
||||
// remove non unimodule dependencies
|
||||
for (const pkg of Object.keys(map)) {
|
||||
map[pkg].dependencies = filter(map[pkg].dependencies, (dep) => !!map[dep]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
async function getPackage(workingdir: string, pkgName: string): Promise<IPackageInfo | null> {
|
||||
const pkgPath = path.join(workingdir, 'packages', pkgName);
|
||||
const isAndroid = await fs.pathExists(path.join(pkgPath, 'android'));
|
||||
const isIos = await fs.pathExists(path.join(pkgPath, 'ios'));
|
||||
const isUnimodule = await fs.pathExists(path.join(pkgPath, 'unimodule.json'));
|
||||
const hasPackageJson = await fs.pathExists(path.join(pkgPath, 'package.json'));
|
||||
if (!isUnimodule || !hasPackageJson || (!isAndroid && !isIos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const packageJson = JSON.parse(await fs.readFile(path.join(pkgPath, 'package.json'), 'utf-8'));
|
||||
|
||||
const pkgDeps = merge({}, // reading everything to make sure
|
||||
packageJson.dependencies,
|
||||
packageJson.peerDependencies,
|
||||
packageJson.unimodulePeerDependencies,
|
||||
);
|
||||
const info: IPackageInfo = {
|
||||
name: packageJson.name,
|
||||
version: packageJson.version,
|
||||
dirname: pkgName,
|
||||
dependencies: Object.keys(pkgDeps),
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -161,10 +161,10 @@
|
||||
mv "~2"
|
||||
safe-json-stringify "~1"
|
||||
|
||||
"@expo/config@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-1.0.2.tgz#1c2c4683895ecc5407f1a3a8868debeee22904bb"
|
||||
integrity sha512-5xp1RLbIxxNw2MwT+zRKdGNMrsPj4OcmBM5T602yQNRc+kmzXAVAHcpVlSk1QfZ5GylTUmGlwcM5X/yhiTBsGw==
|
||||
"@expo/config@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-1.0.3.tgz#7e99eae02f103aa9e2c0597ebef9e509a84ceb7d"
|
||||
integrity sha512-eTX0PedX+x9jjYUlc/dO9lwsLt01V7zDiDsS4n02GVY1X+dLGuq7NiZ3nfazJ3EBE45fJn3lGNydOdRGZFC6lQ==
|
||||
dependencies:
|
||||
"@expo/json-file" "^8.1.2"
|
||||
fs-extra "^7.0.1"
|
||||
@@ -309,10 +309,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@expo/traveling-fastlane-darwin/-/traveling-fastlane-darwin-1.8.1.tgz#37c16a253e92d3ef6f543e7271b7239e6edbbb5f"
|
||||
integrity sha512-Nt+579oBMrMEzVn0Esv7c8nIOwoDX/xS6CThoWPRFMVIeQ52aK1mf7wu91/+FCU/fvfUFZ/evERIDWS1lObRxA==
|
||||
|
||||
"@expo/webpack-config@^0.5.2":
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-0.5.2.tgz#eafc7ac6ec6581629e40962eafe8d71f7c2eef20"
|
||||
integrity sha512-YcySFO5O++UbBJbP1FNHCQJ+RoIvBkUZ8fVcQ/46mdMSULsZoiNouUG4bJUhFiAdzwbzwIv8psOdp7hhLcCKMQ==
|
||||
"@expo/webpack-config@^0.5.3":
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-0.5.3.tgz#51b0d376b6404f1eeb61fbe6753868d68dcd6973"
|
||||
integrity sha512-mltsA3jLK4gld7uzjWdzeEVvOQG9fuj1fTFC3zVH/AZrxi8NDWspZOGdtucew20RkqzZTNgLrMiZ+n56n6mGnw==
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/polyfill" "^7.2.5"
|
||||
@@ -13069,19 +13069,19 @@ xdg-basedir@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
|
||||
integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
|
||||
|
||||
[email protected].3:
|
||||
version "53.5.3"
|
||||
resolved "https://registry.yarnpkg.com/xdl/-/xdl-53.5.3.tgz#2aa96cd67772372d9d4abfc54a026a390b0d631b"
|
||||
integrity sha512-zN4/Urah/VyLBA8bdAlDVgsp2EaxMklVx0TMAU86ftuzmgeUBvvLMd5/wVuiVhlNg8sKsav4T/cWTPgk8ukE/Q==
|
||||
[email protected].4:
|
||||
version "53.5.4"
|
||||
resolved "https://registry.yarnpkg.com/xdl/-/xdl-53.5.4.tgz#50e300bb89cd2703f7a458227eba5e4aa3a16863"
|
||||
integrity sha512-1H4xYzm51zQD9KaifOf2ike3DByHGpdIjYM2TRjCBwPbi82mVbeXUiGL+0azYcHCWqE07LnRzMvlcCD9+WhBUg==
|
||||
dependencies:
|
||||
"@expo/bunyan" "3.0.2"
|
||||
"@expo/config" "^1.0.2"
|
||||
"@expo/config" "^1.0.3"
|
||||
"@expo/json-file" "^8.1.2"
|
||||
"@expo/ngrok" "2.4.3"
|
||||
"@expo/osascript" "^1.9.2"
|
||||
"@expo/schemer" "^1.2.4"
|
||||
"@expo/spawn-async" "1.4.2"
|
||||
"@expo/webpack-config" "^0.5.2"
|
||||
"@expo/webpack-config" "^0.5.3"
|
||||
analytics-node "^2.1.0"
|
||||
axios v0.19.0-beta.1
|
||||
chalk "2.4.1"
|
||||
|
||||
Reference in new issue
Block a user