diff --git a/Releases.md b/Releases.md index c0f5a0443..b107bcb02 100644 --- a/Releases.md +++ b/Releases.md @@ -13,10 +13,6 @@ Release schedule: - 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 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 git cherry-pick commitHash1 -# test everything again using sinopia +# test everything again ./scripts/test-manual-e2e.sh # Check that you can Reload JS and the Chrome debugger works diff --git a/circle.yml b/circle.yml index 6d46aca4f..74a18fc0f 100644 --- a/circle.yml +++ b/circle.yml @@ -32,8 +32,6 @@ dependencies: - npm install # for eslint bot - npm install github@0.2.4 - # for deployment scripts - - npm install shelljs@0.6.0 - cd website && npm install cache_directories: - "ReactAndroid/build/downloads" @@ -78,7 +76,6 @@ test: - ./gradlew :ReactAndroid:installDebugAndroidTest - 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 # testing docs generation is not broken diff --git a/package.json b/package.json index 993bd7abb..7758fc1df 100644 --- a/package.json +++ b/package.json @@ -186,6 +186,7 @@ "flow-bin": "0.22.0", "jest-cli": "0.9.2", "portfinder": "0.4.0", - "react": "^0.14.5" + "react": "^0.14.5", + "shelljs": "0.6.0" } } diff --git a/react-native-cli/index.js b/react-native-cli/index.js index 37a7b2b42..56ab767a8 100755 --- a/react-native-cli/index.js +++ b/react-native-cli/index.js @@ -42,6 +42,19 @@ var spawn = require('child_process').spawn; var chalk = require('chalk'); var prompt = require('prompt'); 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 - 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() { return path.resolve( @@ -69,34 +82,34 @@ if (fs.existsSync(cliPath)) { cli = require(cliPath); } +// minimist api +var commands = argv._; if (cli) { cli.run(); } else { - var args = process.argv.slice(2); - if (args.length === 0) { + if (commands.length === 0) { console.error( 'You did not pass any commands, did you mean to run `react-native init`?' ); process.exit(1); } - switch (args[0]) { + switch (commands[0]) { case 'init': - if (args[1]) { - var verbose = process.argv.indexOf('--verbose') >= 0; - init(args[1], verbose); - } else { + if (!commands[1]) { console.error( 'Usage: react-native init [--verbose]' ); process.exit(1); + } else { + init(commands[1], argv.verbose, argv.version); } break; default: console.error( 'Command `%s` unrecognized. ' + 'Did you mean to run this inside a react-native project?', - args[0] + commands[0] ); process.exit(1); break; @@ -123,17 +136,17 @@ function validatePackageName(name) { } } -function init(name, verbose) { +function init(name, verbose, rnPackage) { validatePackageName(name); if (fs.existsSync(name)) { - createAfterConfirmation(name, verbose); + createAfterConfirmation(name, verbose, rnPackage); } else { - createProject(name, verbose); + createProject(name, verbose, rnPackage); } } -function createAfterConfirmation(name, verbose) { +function createAfterConfirmation(name, verbose, rnPackage) { prompt.start(); var property = { @@ -146,7 +159,7 @@ function createAfterConfirmation(name, verbose) { prompt.get(property, function (err, result) { if (result.yesno[0] === 'y') { - createProject(name, verbose); + createProject(name, verbose, rnPackage); } else { console.log('Project initialization canceled'); 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 projectName = path.basename(root); @@ -181,14 +194,26 @@ function createProject(name, verbose) { console.log('Installing react-native package from npm...'); if (verbose) { - runVerbose(root, projectName); + runVerbose(root, projectName, rnPackage); } else { - run(root, projectName); + run(root, projectName, rnPackage); } } -function run(root, projectName) { - exec('npm install --save react-native', function(e, stdout, stderr) { +function getInstallPackage(rnPackage) { + 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) { console.log(stdout); console.error(stderr); @@ -203,8 +228,8 @@ function run(root, projectName) { }); } -function runVerbose(root, projectName) { - var proc = spawn('npm', ['install', '--verbose', '--save', 'react-native'], {stdio: 'inherit'}); +function runVerbose(root, projectName, rnPackage) { + var proc = spawn('npm', ['install', '--verbose', '--save', getInstallPackage(rnPackage)], {stdio: 'inherit'}); proc.on('close', function (code) { if (code !== 0) { console.error('`npm install --save react-native` failed'); @@ -233,7 +258,7 @@ function checkNodeVersion() { } 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); try { console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version); diff --git a/react-native-cli/package.json b/react-native-cli/package.json index d1de18e2d..e0cf94a5d 100644 --- a/react-native-cli/package.json +++ b/react-native-cli/package.json @@ -1,7 +1,7 @@ { "name": "react-native-cli", - "version": "0.1.10", - "license" : "BSD-3-Clause", + "version": "0.2.0", + "license": "BSD-3-Clause", "description": "The React Native CLI tools", "main": "index.js", "engines": { @@ -19,6 +19,7 @@ }, "dependencies": { "chalk": "^1.1.1", + "minimist": "^1.2.0", "prompt": "^0.2.14", "semver": "^5.0.3" } diff --git a/scripts/e2e-npmrc b/scripts/e2e-npmrc deleted file mode 100644 index 6eb1b2726..000000000 --- a/scripts/e2e-npmrc +++ /dev/null @@ -1,5 +0,0 @@ -; travis:travis -_auth=dHJhdmlzOnRyYXZpcw== -email=travis@example.com -spin=false -registry=http://localhost:4873/ diff --git a/scripts/e2e-sinopia-lego.config.yml b/scripts/e2e-sinopia-lego.config.yml deleted file mode 100644 index ebf99e001..000000000 --- a/scripts/e2e-sinopia-lego.config.yml +++ /dev/null @@ -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' \ No newline at end of file diff --git a/scripts/e2e-sinopia.config.yml b/scripts/e2e-sinopia.config.yml deleted file mode 100644 index 1739d0454..000000000 --- a/scripts/e2e-sinopia.config.yml +++ /dev/null @@ -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' diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh index 6147789ed..70c3484a3 100755 --- a/scripts/e2e-test.sh +++ b/scripts/e2e-test.sh @@ -43,39 +43,23 @@ function cleanup { rm $MARKER_IOS rm $MARKER_ANDROID - [ $SINOPIA_PID ] && kill -9 $SINOPIA_PID [ $SERVER_PID ] && kill -9 $SERVER_PID - [ -f ~/.npmrc.bak ] && mv ~/.npmrc.bak ~/.npmrc } 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 -# sinopia is npm registry proxy, it is used to make npm -# think react-native and react-native-cli are actually -# 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 +npm install -g $CLI_PACKAGE +react-native init EndToEndTest --version $PACKAGE cd EndToEndTest case $1 in @@ -83,6 +67,7 @@ case $1 in echo "Running a basic packager test" # 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 + # TODO do flow check ;; "--ios"*) echo "Running an iOS app" diff --git a/scripts/test-manual-e2e.sh b/scripts/test-manual-e2e.sh index 5d4af5567..94a7fecb8 100755 --- a/scripts/test-manual-e2e.sh +++ b/scripts/test-manual-e2e.sh @@ -1,6 +1,5 @@ #! /bin/bash -RELEASE="$1" JAVA_VERSION="1.7" RED="\033[0;31m" @@ -21,43 +20,34 @@ info() { 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) -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" 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}" - -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})" +PACKAGE=$(pwd)/react-native-$PACKAGE_VERSION.tgz +success "Package bundled ($PACKAGE)" project_name="RNTestProject" cd /tmp/ 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:" -grep "\"react-native\": \"\^${RELEASE}.0-rc\"" "/tmp/${project_name}/package.json" || error "Incorrect version number in /tmp/${project_name}/package.json" +info "Double checking the versions in package.json are correct:" +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:+" 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 "Press any key to run the sample in Android emulator/device" +info "" 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 "" read -n 1 open "/tmp/${project_name}/ios/${project_name}.xcodeproj" 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 " - git tag v${RELEASE}.0-rc" -info " - git push origin ${RELEASE}-stable --tags" +info " - https://github.com/facebook/react-native/blob/master/Releases.md"