diff --git a/.flowconfig b/.flowconfig index bad57bc52f6..5cfdb69fa30 100644 --- a/.flowconfig +++ b/.flowconfig @@ -7,6 +7,7 @@ /.*/__tests__/.* # Ignore Docs +/docs/.* /.*/docs/.* [include] diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000000..3b8e1bb3fa4 --- /dev/null +++ b/circle.yml @@ -0,0 +1,42 @@ +--- +general: + branches: + ignore: + - gh-pages + +machine: + timezone: America/Los_Angeles + node: + version: 6 + ruby: + version: 2.2.3 + environment: + TRAVIS_REPO_SLUG: facebook/react + +dependencies: + pre: + # This is equivalent to $TRAVIS_COMMIT_RANGE + # Need to figure out how to bail early if this is a "docs only" build + - echo $CIRCLE_COMPARE_URL | cut -d/ -f7 + override: + - bundle install --gemfile=docs/Gemfile --deployment --path=vendor/bundle --jobs=3 --retry=3 + - npm install + - scripts/circleci/set_up_github_keys.sh + post: + # - npm ls --depth=0 + cache_directories: + - docs/vendor/bundle + - .grunt # Show size comparisons between builds + - ~/react-gh-pages # docs checkout + +test: + override: + - ./scripts/circleci/test_entry_point.sh: + parallel: true + +deployment: + staging: + branch: /.*/ + commands: + - ./scripts/circleci/upload_build.sh + - ./scripts/circleci/build_gh_pages.sh diff --git a/fixtures/browserify/input.js b/fixtures/browserify/input.js index da6cc5d0ff1..4ab5502dd32 100644 --- a/fixtures/browserify/input.js +++ b/fixtures/browserify/input.js @@ -1,3 +1,5 @@ +'use strict'; + var React = require('react'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var ReactDOM = require('react-dom'); diff --git a/fixtures/brunch/app/initialize.js b/fixtures/brunch/app/initialize.js index da6cc5d0ff1..4ab5502dd32 100644 --- a/fixtures/brunch/app/initialize.js +++ b/fixtures/brunch/app/initialize.js @@ -1,3 +1,5 @@ +'use strict'; + var React = require('react'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var ReactDOM = require('react-dom'); diff --git a/fixtures/brunch/config.js b/fixtures/brunch/config.js index ba12fc72c23..c8733fdb678 100644 --- a/fixtures/brunch/config.js +++ b/fixtures/brunch/config.js @@ -1,3 +1,5 @@ +'use strict'; + exports.config = { paths: { public: '.', diff --git a/fixtures/brunch/input.js b/fixtures/brunch/input.js index da6cc5d0ff1..4ab5502dd32 100644 --- a/fixtures/brunch/input.js +++ b/fixtures/brunch/input.js @@ -1,3 +1,5 @@ +'use strict'; + var React = require('react'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var ReactDOM = require('react-dom'); diff --git a/fixtures/build-all.js b/fixtures/build-all.js index b5620c0fa32..84b8decc3bc 100644 --- a/fixtures/build-all.js +++ b/fixtures/build-all.js @@ -1,3 +1,5 @@ +'use strict'; + var fs = require('fs'); var path = require('path'); var { spawnSync } = require('child_process'); diff --git a/fixtures/rjs/config.js b/fixtures/rjs/config.js index f15dc110035..20d2d32b93e 100644 --- a/fixtures/rjs/config.js +++ b/fixtures/rjs/config.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = { baseUrl: '.', name: 'input', diff --git a/fixtures/rjs/input.js b/fixtures/rjs/input.js index 2b0deee96c2..cbda88d7ef6 100644 --- a/fixtures/rjs/input.js +++ b/fixtures/rjs/input.js @@ -1,3 +1,5 @@ +'use strict'; + require(['react', 'react-dom'], function(React, ReactDOM) { var CSSTransitionGroup = React.addons.CSSTransitionGroup; ReactDOM.render( diff --git a/fixtures/systemjs-builder/build.js b/fixtures/systemjs-builder/build.js index d476c09a646..c596c882c3a 100644 --- a/fixtures/systemjs-builder/build.js +++ b/fixtures/systemjs-builder/build.js @@ -1,3 +1,5 @@ +'use strict'; + var Builder = require('systemjs-builder'); var builder = new Builder('/', './config.js'); diff --git a/fixtures/systemjs-builder/config.js b/fixtures/systemjs-builder/config.js index baed2db8c62..1fcfe2d2b7c 100644 --- a/fixtures/systemjs-builder/config.js +++ b/fixtures/systemjs-builder/config.js @@ -1,3 +1,5 @@ +'use strict'; + System.config({ paths: { react: '../../build/react-with-addons.js', diff --git a/fixtures/systemjs-builder/input.js b/fixtures/systemjs-builder/input.js index 27d5c10086c..78e914c5517 100644 --- a/fixtures/systemjs-builder/input.js +++ b/fixtures/systemjs-builder/input.js @@ -1,3 +1,5 @@ +'use strict'; + import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/fixtures/webpack-alias/config.js b/fixtures/webpack-alias/config.js index dcc0c3a9072..7ba98467a5f 100644 --- a/fixtures/webpack-alias/config.js +++ b/fixtures/webpack-alias/config.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = { entry: './input', output: { diff --git a/fixtures/webpack-alias/input.js b/fixtures/webpack-alias/input.js index f1e2d79e23c..57b7e94cc90 100644 --- a/fixtures/webpack-alias/input.js +++ b/fixtures/webpack-alias/input.js @@ -1,3 +1,5 @@ +'use strict'; + var React = require('react'); var ReactDOM = require('react-dom'); diff --git a/fixtures/webpack/config.js b/fixtures/webpack/config.js index 685cac24ee9..e00ada05a6c 100644 --- a/fixtures/webpack/config.js +++ b/fixtures/webpack/config.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = { entry: './input', output: { diff --git a/fixtures/webpack/input.js b/fixtures/webpack/input.js index da6cc5d0ff1..4ab5502dd32 100644 --- a/fixtures/webpack/input.js +++ b/fixtures/webpack/input.js @@ -1,3 +1,5 @@ +'use strict'; + var React = require('react'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var ReactDOM = require('react-dom'); diff --git a/grunt/tasks/jest.js b/grunt/tasks/jest.js index d48d6f1f0c3..7bccf5dfe72 100644 --- a/grunt/tasks/jest.js +++ b/grunt/tasks/jest.js @@ -8,6 +8,7 @@ function run(done, coverage) { var args = [ path.join('node_modules', 'jest', 'bin', 'jest'), + '--runInBand', ]; if (coverage) { args.push('--coverage'); diff --git a/package.json b/package.json index 8f16f2b36c7..737754e0f30 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "gulp-util": "^3.0.7", "gzip-js": "~0.3.2", "jest": "^15.1.1", + "jest-cli": "^15.1.1", "loose-envify": "^1.1.0", "merge-stream": "^1.0.0", "object-assign": "^4.1.0", diff --git a/scripts/circleci/build_gh_pages.sh b/scripts/circleci/build_gh_pages.sh new file mode 100755 index 00000000000..fcf49f2af95 --- /dev/null +++ b/scripts/circleci/build_gh_pages.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +if [ -z $CI_PULL_REQUEST ] && [ "$CIRCLE_BRANCH" = "$REACT_WEBSITE_BRANCH" ]; then + + GH_PAGES_DIR=`pwd`/../react-gh-pages + + # check if directory exists (restored from cache) + if [ -d $GH_PAGES_DIR ]; then + pushd $GH_PAGES_DIR + git pull origin gh-pages + popd + else + git clone --branch gh-pages --depth=1 \ + https://reactjs-bot@github.com/facebook/react.git \ + $GH_PAGES_DIR + fi + + pushd docs + bundle exec rake release + cd $GH_PAGES_DIR + git status + git --no-pager diff + if ! git diff-index --quiet HEAD --; then + git add -A . + git commit -m "Rebuild website" + git push origin gh-pages + fi + popd +else + echo "Not building website" +fi diff --git a/scripts/circleci/set_up_github_keys.sh b/scripts/circleci/set_up_github_keys.sh new file mode 100755 index 00000000000..302c40eef0e --- /dev/null +++ b/scripts/circleci/set_up_github_keys.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +if [ -n $GITHUB_TOKEN ]; then + + GH_PAGES_DIR=`pwd`/../react-gh-pages + echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" >~/.netrc + git config --global user.name "Circle CI" + git config --global user.email "circle@reactjs.org" + +fi diff --git a/scripts/circleci/test_coverage.sh b/scripts/circleci/test_coverage.sh new file mode 100755 index 00000000000..05a717c2a41 --- /dev/null +++ b/scripts/circleci/test_coverage.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +./node_modules/.bin/grunt jest:coverage +if [ -z $CI_PULL_REQUEST ]; then + cat ./coverage/lcov.info | ./node_modules/.bin/coveralls +fi diff --git a/scripts/circleci/test_entry_point.sh b/scripts/circleci/test_entry_point.sh new file mode 100755 index 00000000000..2f9c042f7e8 --- /dev/null +++ b/scripts/circleci/test_entry_point.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -e + +COMMANDS_TO_RUN=() + +# We split these to be approximately equal chunks of four. As of this writing, +# times were around: +# - 3:30 test_coverage.sh +# - 2:00 test_fiber.sh +# - 1:15 test_html_generation.sh +# - 1:15 grunt build +# with everything else < 0:30. + +if [ $((1 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then + COMMANDS_TO_RUN+=('./scripts/circleci/test_coverage.sh') +fi + +if [ $((2 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then + COMMANDS_TO_RUN+=('./scripts/circleci/test_html_generation.sh') +fi + +# These seem out of order but extract-errors must be run after jest. +if [ $((0 % CIRCLE_NODE_TOTAL)) -eq "$CIRCLE_NODE_INDEX" ]; then + COMMANDS_TO_RUN+=('./node_modules/.bin/gulp lint') + COMMANDS_TO_RUN+=('./node_modules/.bin/gulp flow') + COMMANDS_TO_RUN+=('./node_modules/.bin/grunt build') + COMMANDS_TO_RUN+=('./scripts/circleci/test_extract_errors.sh') + COMMANDS_TO_RUN+=('./scripts/circleci/track_stats.sh') +fi + +RETURN_CODES=() +FAILURE=0 + +printf "Node #%s (%s total). " "$CIRCLE_NODE_INDEX" "$CIRCLE_NODE_TOTAL" +if [ -n "${COMMANDS_TO_RUN[0]}" ]; then + echo "Preparing to run commands:" + for cmd in "${COMMANDS_TO_RUN[@]}"; do + echo "- $cmd" + done + + for cmd in "${COMMANDS_TO_RUN[@]}"; do + echo + echo "$ $cmd" + set +e + $cmd + rc=$? + set -e + RETURN_CODES+=($rc) + if [ $rc -ne 0 ]; then + FAILURE=$rc + fi + done + + echo + for i in "${!COMMANDS_TO_RUN[@]}"; do + echo "Received return code ${RETURN_CODES[i]} from: ${COMMANDS_TO_RUN[i]}" + done + exit $FAILURE +else + echo "No commands to run." +fi diff --git a/scripts/circleci/test_extract_errors.sh b/scripts/circleci/test_extract_errors.sh new file mode 100755 index 00000000000..5169752509e --- /dev/null +++ b/scripts/circleci/test_extract_errors.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +./node_modules/.bin/gulp react:extract-errors +git checkout -- scripts/error-codes/codes.json diff --git a/scripts/circleci/test_html_generation.sh b/scripts/circleci/test_html_generation.sh new file mode 100755 index 00000000000..0bedb26aea4 --- /dev/null +++ b/scripts/circleci/test_html_generation.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +echo 'Testing in server-render (HTML generation) mode...' +printf '\nmodule.exports.useCreateElement = false;\n' \ + >> src/renderers/dom/shared/ReactDOMFeatureFlags.js +./node_modules/.bin/grunt jest:normal +git checkout -- src/renderers/dom/shared/ReactDOMFeatureFlags.js diff --git a/scripts/circleci/track_stats.sh b/scripts/circleci/track_stats.sh new file mode 100755 index 00000000000..a8a3eae1fad --- /dev/null +++ b/scripts/circleci/track_stats.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +ALL_FILES=`find src -name '*.js' | grep -v umd/ | grep -v __tests__ | grep -v __mocks__` +COUNT_ALL_FILES=`echo "$ALL_FILES" | wc -l` +COUNT_WITH_FLOW=`grep '@flow' $ALL_FILES | perl -pe 's/:.+//' | wc -l` +node scripts/facts-tracker/index.js "flow-files" "$COUNT_WITH_FLOW/$COUNT_ALL_FILES" diff --git a/scripts/circleci/upload_build.sh b/scripts/circleci/upload_build.sh new file mode 100755 index 00000000000..0558ba8dd05 --- /dev/null +++ b/scripts/circleci/upload_build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +if [ -z $CI_PULL_REQUEST ] && [ -n "$BUILD_SERVER_ENDPOINT" ]; then + curl \ + -F "react=@build/react.js" \ + -F "react.min=@build/react.min.js" \ + -F "react-with-addons=@build/react-with-addons.js" \ + -F "react-with-addons.min=@build/react-with-addons.min.js" \ + -F "react-dom=@build/react-dom.js" \ + -F "react-dom.min=@build/react-dom.min.js" \ + -F "react-dom-server=@build/react-dom-server.js" \ + -F "react-dom-server.min=@build/react-dom-server.min.js" \ + -F "npm-react=@build/packages/react.tgz" \ + -F "npm-react-dom=@build/packages/react-dom.tgz" \ + -F "commit=$CIRCLE_SHA1" \ + -F "date=`git log --format='%ct' -1`" \ + -F "pull_request=false" \ + -F "token=$BUILD_SERVER_TOKEN" \ + -F "branch=$CIRCLE_BRANCH" \ + $BUILD_SERVER_ENDPOINT +fi