Allow react-native init <version> + removed sinopia from being required for e2e testing

Reviewed By: mkonicek, frantic

Differential Revision: D3087524

fb-gh-sync-id: 048e23b55916a6be17fa9fabb6e41b0b2f3f7a16
shipit-source-id: 048e23b55916a6be17fa9fabb6e41b0b2f3f7a16
This commit is contained in:
Konstantin Raev 2016-03-24 05:30:49 -07:00 committed by Facebook Github Bot 9
parent ad41a0b326
commit 993835c815
10 changed files with 82 additions and 145 deletions

View File

@ -13,10 +13,6 @@ Release schedule:
- 0.24.0 - Apr 18 - 0.24.0 - Apr 18
- ... - ...
## One time setup
Set up Sinopia: https://github.com/facebook/react-native/tree/master/react-native-cli
#### Check that everything works #### Check that everything works
Make absolutely sure a basic iOS and Android workflow works on the commit you are going to use for release. Make absolutely sure a basic iOS and Android workflow works on the commit you are going to use for release.
@ -79,7 +75,7 @@ git pull origin 0.version_you_are_releasing-stable # e.g. git pull origin 0.22-
# Cherry-pick those commits # Cherry-pick those commits
git cherry-pick commitHash1 git cherry-pick commitHash1
# test everything again using sinopia # test everything again
./scripts/test-manual-e2e.sh ./scripts/test-manual-e2e.sh
# Check that you can Reload JS and the Chrome debugger works # Check that you can Reload JS and the Chrome debugger works

View File

@ -32,8 +32,6 @@ dependencies:
- npm install - npm install
# for eslint bot # for eslint bot
- npm install github@0.2.4 - npm install github@0.2.4
# for deployment scripts
- npm install shelljs@0.6.0
- cd website && npm install - cd website && npm install
cache_directories: cache_directories:
- "ReactAndroid/build/downloads" - "ReactAndroid/build/downloads"
@ -78,7 +76,6 @@ test:
- ./gradlew :ReactAndroid:installDebugAndroidTest - ./gradlew :ReactAndroid:installDebugAndroidTest
- source scripts/circle-ci-android-setup.sh && retry3 ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests.gradle - source scripts/circle-ci-android-setup.sh && retry3 ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests.gradle
# Publish to Sinopia, create a new app using 'react-native init' and check the packager starts
- ./scripts/e2e-test.sh --packager - ./scripts/e2e-test.sh --packager
# testing docs generation is not broken # testing docs generation is not broken

View File

@ -186,6 +186,7 @@
"flow-bin": "0.22.0", "flow-bin": "0.22.0",
"jest-cli": "0.9.2", "jest-cli": "0.9.2",
"portfinder": "0.4.0", "portfinder": "0.4.0",
"react": "^0.14.5" "react": "^0.14.5",
"shelljs": "0.6.0"
} }
} }

View File

@ -42,6 +42,19 @@ var spawn = require('child_process').spawn;
var chalk = require('chalk'); var chalk = require('chalk');
var prompt = require('prompt'); var prompt = require('prompt');
var semver = require('semver'); var semver = require('semver');
/**
* Used arguments:
* -v --version - to print current version of react-native-cli and react-native dependency
* if you are in a RN app folder
* init - to create a new project and npm install it
* --verbose - to print logs while init
* --version <alternative react-native package> - override default (https://registry.npmjs.org/react-native@latest),
* package to install, examples:
* - "0.22.0-rc1" - A new app will be created using a specific version of React Native from npm repo
* - "https://registry.npmjs.org/react-native/-/react-native-0.20.0.tgz" - a .tgz archive from any npm repo
* - "/Users/home/react-native/react-native-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests
*/
var argv = require('minimist')(process.argv.slice(2));
var CLI_MODULE_PATH = function() { var CLI_MODULE_PATH = function() {
return path.resolve( return path.resolve(
@ -69,34 +82,34 @@ if (fs.existsSync(cliPath)) {
cli = require(cliPath); cli = require(cliPath);
} }
// minimist api
var commands = argv._;
if (cli) { if (cli) {
cli.run(); cli.run();
} else { } else {
var args = process.argv.slice(2); if (commands.length === 0) {
if (args.length === 0) {
console.error( console.error(
'You did not pass any commands, did you mean to run `react-native init`?' 'You did not pass any commands, did you mean to run `react-native init`?'
); );
process.exit(1); process.exit(1);
} }
switch (args[0]) { switch (commands[0]) {
case 'init': case 'init':
if (args[1]) { if (!commands[1]) {
var verbose = process.argv.indexOf('--verbose') >= 0;
init(args[1], verbose);
} else {
console.error( console.error(
'Usage: react-native init <ProjectName> [--verbose]' 'Usage: react-native init <ProjectName> [--verbose]'
); );
process.exit(1); process.exit(1);
} else {
init(commands[1], argv.verbose, argv.version);
} }
break; break;
default: default:
console.error( console.error(
'Command `%s` unrecognized. ' + 'Command `%s` unrecognized. ' +
'Did you mean to run this inside a react-native project?', 'Did you mean to run this inside a react-native project?',
args[0] commands[0]
); );
process.exit(1); process.exit(1);
break; break;
@ -123,17 +136,17 @@ function validatePackageName(name) {
} }
} }
function init(name, verbose) { function init(name, verbose, rnPackage) {
validatePackageName(name); validatePackageName(name);
if (fs.existsSync(name)) { if (fs.existsSync(name)) {
createAfterConfirmation(name, verbose); createAfterConfirmation(name, verbose, rnPackage);
} else { } else {
createProject(name, verbose); createProject(name, verbose, rnPackage);
} }
} }
function createAfterConfirmation(name, verbose) { function createAfterConfirmation(name, verbose, rnPackage) {
prompt.start(); prompt.start();
var property = { var property = {
@ -146,7 +159,7 @@ function createAfterConfirmation(name, verbose) {
prompt.get(property, function (err, result) { prompt.get(property, function (err, result) {
if (result.yesno[0] === 'y') { if (result.yesno[0] === 'y') {
createProject(name, verbose); createProject(name, verbose, rnPackage);
} else { } else {
console.log('Project initialization canceled'); console.log('Project initialization canceled');
process.exit(); process.exit();
@ -154,7 +167,7 @@ function createAfterConfirmation(name, verbose) {
}); });
} }
function createProject(name, verbose) { function createProject(name, verbose, rnPackage) {
var root = path.resolve(name); var root = path.resolve(name);
var projectName = path.basename(root); var projectName = path.basename(root);
@ -181,14 +194,26 @@ function createProject(name, verbose) {
console.log('Installing react-native package from npm...'); console.log('Installing react-native package from npm...');
if (verbose) { if (verbose) {
runVerbose(root, projectName); runVerbose(root, projectName, rnPackage);
} else { } else {
run(root, projectName); run(root, projectName, rnPackage);
} }
} }
function run(root, projectName) { function getInstallPackage(rnPackage) {
exec('npm install --save react-native', function(e, stdout, stderr) { var packageToInstall = 'react-native';
var valideSemver = semver.valid(rnPackage);
if (valideSemver) {
packageToInstall += '@' + valideSemver;
} else if (rnPackage) {
// for tar.gz or alternative paths
packageToInstall = rnPackage;
}
return packageToInstall;
}
function run(root, projectName, rnPackage) {
exec('npm install --save ' + getInstallPackage(rnPackage), function(e, stdout, stderr) {
if (e) { if (e) {
console.log(stdout); console.log(stdout);
console.error(stderr); console.error(stderr);
@ -203,8 +228,8 @@ function run(root, projectName) {
}); });
} }
function runVerbose(root, projectName) { function runVerbose(root, projectName, rnPackage) {
var proc = spawn('npm', ['install', '--verbose', '--save', 'react-native'], {stdio: 'inherit'}); var proc = spawn('npm', ['install', '--verbose', '--save', getInstallPackage(rnPackage)], {stdio: 'inherit'});
proc.on('close', function (code) { proc.on('close', function (code) {
if (code !== 0) { if (code !== 0) {
console.error('`npm install --save react-native` failed'); console.error('`npm install --save react-native` failed');
@ -233,7 +258,7 @@ function checkNodeVersion() {
} }
function checkForVersionArgument() { function checkForVersionArgument() {
if (process.argv.indexOf('-v') >= 0 || process.argv.indexOf('--version') >= 0) { if (argv._.length === 0 && (argv.v || argv.version)) {
console.log('react-native-cli: ' + require('./package.json').version); console.log('react-native-cli: ' + require('./package.json').version);
try { try {
console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version); console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version);

View File

@ -1,6 +1,6 @@
{ {
"name": "react-native-cli", "name": "react-native-cli",
"version": "0.1.10", "version": "0.2.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"description": "The React Native CLI tools", "description": "The React Native CLI tools",
"main": "index.js", "main": "index.js",
@ -19,6 +19,7 @@
}, },
"dependencies": { "dependencies": {
"chalk": "^1.1.1", "chalk": "^1.1.1",
"minimist": "^1.2.0",
"prompt": "^0.2.14", "prompt": "^0.2.14",
"semver": "^5.0.3" "semver": "^5.0.3"
} }

View File

@ -1,5 +0,0 @@
; travis:travis
_auth=dHJhdmlzOnRyYXZpcw==
email=travis@example.com
spin=false
registry=http://localhost:4873/

View File

@ -1,23 +0,0 @@
storage: /tmp/sinopia-package-cache
uplinks:
npmjs:
url: http://registry.npmjs.org/
packages:
'react-native':
allow_access: $all
allow_publish: $all
'react-native-cli':
allow_access: $all
allow_publish: $all
'*':
allow_access: $all
proxy: npmjs
logs:
- {type: file, path: sinopia.log, format: pretty, level: http}
max_body_size: '50mb'

View File

@ -1,23 +0,0 @@
storage: /tmp/sinopia-package-cache
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'react-native':
allow_access: $all
allow_publish: $all
'react-native-cli':
allow_access: $all
allow_publish: $all
'*':
allow_access: $all
proxy: npmjs
logs:
- {type: file, path: sinopia.log, format: pretty, level: http}
max_body_size: '50mb'

View File

@ -43,39 +43,23 @@ function cleanup {
rm $MARKER_IOS rm $MARKER_IOS
rm $MARKER_ANDROID rm $MARKER_ANDROID
[ $SINOPIA_PID ] && kill -9 $SINOPIA_PID
[ $SERVER_PID ] && kill -9 $SERVER_PID [ $SERVER_PID ] && kill -9 $SERVER_PID
[ -f ~/.npmrc.bak ] && mv ~/.npmrc.bak ~/.npmrc
} }
trap cleanup EXIT trap cleanup EXIT
# pack react-native into a .tgz file
npm pack
PACKAGE=$(pwd)/react-native-*.tgz
# get react-native-cli dependencies
cd react-native-cli
npm pack
CLI_PACKAGE=$(pwd)/react-native-cli-*.tgz
cd $TEMP cd $TEMP
# sinopia is npm registry proxy, it is used to make npm npm install -g $CLI_PACKAGE
# think react-native and react-native-cli are actually react-native init EndToEndTest --version $PACKAGE
# published on npm
# Temporarily installing sinopia from a github fork
# TODO t10060166 use npm repo when bug is fixed
which sinopia || npm install -g git://github.com/bestander/sinopia.git#68707efbab90569d5f52193138936f9281cc410c
# but in order to make npm use sinopia we temporarily
# replace its config file
[ -f ~/.npmrc ] && cp ~/.npmrc ~/.npmrc.bak
cp $SCRIPTS/e2e-npmrc ~/.npmrc
sinopia --config $SCRIPTS/e2e-sinopia.config.yml &
SINOPIA_PID=$!
# Make sure to remove old version of react-native in
# case it was cached
npm cache clear
npm unpublish react-native --force
npm unpublish react-native-cli --force
npm publish $ROOT
npm publish $ROOT/react-native-cli
npm install -g react-native-cli
react-native init EndToEndTest
cd EndToEndTest cd EndToEndTest
case $1 in case $1 in
@ -83,6 +67,7 @@ case $1 in
echo "Running a basic packager test" echo "Running a basic packager test"
# Check the packager produces a bundle (doesn't throw an error) # Check the packager produces a bundle (doesn't throw an error)
react-native bundle --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js react-native bundle --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js
# TODO do flow check
;; ;;
"--ios"*) "--ios"*)
echo "Running an iOS app" echo "Running an iOS app"

View File

@ -1,6 +1,5 @@
#! /bin/bash #! /bin/bash
RELEASE="$1"
JAVA_VERSION="1.7" JAVA_VERSION="1.7"
RED="\033[0;31m" RED="\033[0;31m"
@ -21,43 +20,34 @@ info() {
echo -e $BLUE"$@"$ENDCOLOR echo -e $BLUE"$@"$ENDCOLOR
} }
[[ -z $RELEASE ]] && error "Please specify a version. Example usage: release.sh 0.18" PACKAGE_VERSION=$(cat package.json \
| grep version \
| head -1 \
| awk -F: '{ print $2 }' \
| sed 's/[",]//g' \
| tr -d '[[:space:]]')
success "Preparing version $PACKAGE_VERSION"
repo_root=$(pwd) repo_root=$(pwd)
sed -i.bak s/^VERSION_NAME=[0-9\.]*-SNAPSHOT/VERSION_NAME=${RELEASE}.0/g "ReactAndroid/gradle.properties" || error "Couldn't update version for Gradle"
./gradlew :ReactAndroid:installArchives || error "Couldn't generate artifacts" ./gradlew :ReactAndroid:installArchives || error "Couldn't generate artifacts"
success "Generated artifacts for Maven" success "Generated artifacts for Maven"
npm_registry="http://localhost:4873/" npm pack
npm set registry "${npm_registry}" && [[ $(npm config list | grep registry) == "registry = \"${npm_registry}\"" ]] || error "Couldn't set registry to ${npm_registry}" PACKAGE=$(pwd)/react-native-$PACKAGE_VERSION.tgz
success "Package bundled ($PACKAGE)"
info "npm registry set. Run 'sinopia' in a new Terminal"
info " - Make sure it prints 'http address - ${npm_registry}'"
info " - Make sure ${npm_registry} shows no old versions"
info ""
info "Press any key to continue"
read -n 1
sed -i.bak -E "s/(\"version\":[[:space:]]*\").+(\")/\"version\": \"${RELEASE}.0-rc\"/g" "package.json" || error "Couldn't update version for npm"
sed -i.bak -E "s/(s.version[[:space:]]{13}=[[:space:]].+)/s.version = \"${RELEASE}.0-rc\"/g" "React.podspec" || error "Couldn't update version for CocoaPods"
npm unpublish --force || error "Couldn't unpublish package from sinopia (${npm_registry})"
npm publish || error "Couldn't publish package to sinopia (${npm_registry})"
success "Published package to sinopia (${npm_registry})"
project_name="RNTestProject" project_name="RNTestProject"
cd /tmp/ cd /tmp/
rm -rf "$project_name" rm -rf "$project_name"
react-native init "$project_name" react-native init "$project_name" --version $PACKAGE
info "Double checking the versions in package.json and build.gradle are correct:" info "Double checking the versions in package.json are correct:"
grep "\"react-native\": \"\^${RELEASE}.0-rc\"" "/tmp/${project_name}/package.json" || error "Incorrect version number in /tmp/${project_name}/package.json" grep "\"react-native\": \".*react-native-$PACKAGE_VERSION.tgz\"" "/tmp/${project_name}/package.json" || error "Incorrect version number in /tmp/${project_name}/package.json"
grep -E "com.facebook.react:react-native:\\+" "${project_name}/android/app/build.gradle" || error "Dependency in /tmp/${project_name}/android/app/build.gradle must be com.facebook.react:react-native:+" grep -E "com.facebook.react:react-native:\\+" "${project_name}/android/app/build.gradle" || error "Dependency in /tmp/${project_name}/android/app/build.gradle must be com.facebook.react:react-native:+"
success "New sample project generated at /tmp/${project_name}" success "New sample project generated at /tmp/${project_name}"
@ -70,23 +60,16 @@ info " - Test Chrome debugger by adding breakpoints. We don't have tests for C
info "" info ""
info "Press any key to run the sample in Android emulator/device" info "Press any key to run the sample in Android emulator/device"
info ""
read -n 1 read -n 1
cd "${project_name}" && react-native run-android cd "/tmp/${project_name}" && react-native run-android
info "Press any key to open the project in XCode" info "Press any key to open the project in XCode"
info ""
read -n 1 read -n 1
open "/tmp/${project_name}/ios/${project_name}.xcodeproj" open "/tmp/${project_name}/ios/${project_name}.xcodeproj"
cd "$repo_root" cd "$repo_root"
# undo changes to files
git checkout package.json
git checkout React.podspec
git checkout ReactAndroid/gradle.properties
find . -path "*.bak" | xargs rm
npm set registry "https://registry.npmjs.org/" || error "Couldn't set registry to ${npm_registry}"
info "Next steps:" info "Next steps:"
info " - git tag v${RELEASE}.0-rc" info " - https://github.com/facebook/react-native/blob/master/Releases.md"
info " - git push origin ${RELEASE}-stable --tags"