diff --git a/azure-pipelines-test-job.yml b/azure-pipelines-test-job.yml new file mode 100644 index 00000000000..18000d462cb --- /dev/null +++ b/azure-pipelines-test-job.yml @@ -0,0 +1,40 @@ +# +# Azure Pipelines job for building and testing create-react-app on Linux, Windows, and macOS. +# + +parameters: + name: '' + testScript: '' + configurations: + LinuxNode8: { vmImage: 'ubuntu-16.04', nodeVersion: 8.x } + LinuxNode10: { vmImage: 'ubuntu-16.04', nodeVersion: 10.x } + WindowsNode8: { vmImage: 'vs2017-win2016', nodeVersion: 8.x } + WindowsNode10: { vmImage: 'vs2017-win2016', nodeVersion: 10.x } + +jobs: +- job: ${{ parameters.name }} + strategy: + matrix: + ${{ insert }}: ${{ parameters.configurations }} + pool: + vmImage: $(vmImage) + steps: + - script: | + git config --global core.autocrlf false + git config --global user.name "Create React App" + git config --global user.email "cra@email.com" + displayName: 'Initialize Git config' + + - checkout: self + path: create-react-app + + - task: NodeTool@0 + inputs: + versionSpec: $(nodeVersion) + displayName: 'Install Node.js' + + - script: yarn --frozen-lockfile + displayName: 'Run yarn' + + - bash: ${{ parameters.testScript }} + displayName: 'Run tests' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f2894295b66..c51be42da86 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,6 +1,78 @@ -pool: - vmImage: 'Ubuntu 16.04' - -steps: -- script: echo Hello world! - displayName: Say hello +# +# Azure Pipelines configuration for building and testing create-react-app on Linux, Windows, and macOS. +# + +trigger: +- master + +variables: + CI: true + # Overrides the Yarn and NPM cache directories so they are on the same drive as the source. This helps improve build performance on Windows hosted agents. + YARN_CACHE_FOLDER: $(Build.SourcesDirectory)/../yarn-cache + NPM_CONFIG_CACHE: $(Build.SourcesDirectory)/../npm-cache + # Sets TEMP to be on the same drive as the cloned source on Windows. This avoids test scripts that "cd" into a directory under TEMP from failing because this directory is on a different drive from the current directory. + VSTS_OVERWRITE_TEMP: True + # Override Verdaccio package to use. This is temoporary and is needed to avoid socket timeouts on hosted Windows agent (on Azure). This also changes Verdaccio to return a 503 (service unavailable) instead of a 404 (not found) when the connection to the uplink timesout. + VERDACCIO_PACKAGE: https://github.com/willsmythe/verdaccio/releases/download/create-react-app/verdaccio-4.0.0-alpha.8.tgz + +# ****************************************************************************** +# Simple test suite +# ****************************************************************************** +jobs: +- template: azure-pipelines-test-job.yml + parameters: + name: Simple + testScript: tasks/e2e-simple.sh + +# ****************************************************************************** +# Installs test suite +# ****************************************************************************** +- template: azure-pipelines-test-job.yml + parameters: + name: Installs + testScript: tasks/e2e-installs.sh + +# ****************************************************************************** +# Kitchensink test suite +# ****************************************************************************** +- template: azure-pipelines-test-job.yml + parameters: + name: Kitchensink + testScript: tasks/e2e-kitchensink.sh + +# ****************************************************************************** +# Kitchensink Eject test suite +# ****************************************************************************** +- template: azure-pipelines-test-job.yml + parameters: + name: KitchensinkEject + testScript: tasks/e2e-kitchensink-eject.sh + +# ****************************************************************************** +# Behavior test suite +# ****************************************************************************** +- template: azure-pipelines-test-job.yml + parameters: + name: Behavior + testScript: tasks/e2e-behavior.sh + configurations: + LinuxNode8: { vmImage: 'ubuntu-16.04', nodeVersion: 8.x } + LinuxNode10: { vmImage: 'ubuntu-16.04', nodeVersion: 10.x } + WindowsNode8: { vmImage: 'vs2017-win2016', nodeVersion: 8.x } + WindowsNode10: { vmImage: 'vs2017-win2016', nodeVersion: 10.x } + MacNode8: { vmImage: 'macOS-10.13', nodeVersion: 8.x } + MacNode10: { vmImage: 'macOS-10.13', nodeVersion: 10.x } + +# ****************************************************************************** +# Old Node test suite +# ****************************************************************************** +- job: OldNode + pool: + vmImage: ubuntu-16.04 + steps: + - task: NodeTool@0 + inputs: + versionSpec: 6.x + displayName: 'Install Node.js 6.x' + - bash: tasks/e2e-old-node.sh + displayName: 'Run tests' diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index d2c788268b8..7f82f4f7f38 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -34,7 +34,7 @@ module.exports = (resolve, rootDir, isEjecting) => { setupFilesAfterEnv: setupTestsFile ? [setupTestsFile] : [], testMatch: [ '/src/**/__tests__/**/*.{js,jsx,ts,tsx}', - '/src/**/*.{spec,test}.{js,jsx,ts,tsx}', + '/src/**/*(*.)@(spec|test).{js,jsx,ts,tsx}', ], testEnvironment: 'jest-environment-jsdom-fourteen', transform: { diff --git a/tasks/e2e-behavior.sh b/tasks/e2e-behavior.sh index 93a49e5b6b3..68f41d55034 100755 --- a/tasks/e2e-behavior.sh +++ b/tasks/e2e-behavior.sh @@ -15,18 +15,16 @@ cd "$(dirname "$0")" # CLI, app, and test module temporary locations # http://unix.stackexchange.com/a/84980 temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` -temp_module_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_module_path'` -custom_registry_url=http://localhost:4873 -original_npm_registry_url=`npm get registry` -original_yarn_registry_url=`yarn config get registry` + +# Load functions for working with local NPM registry (Verdaccio) +source local-registry.sh function cleanup { - echo 'Cleaning up.' - ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 + echo 'Cleaning up.' ps -ef | grep 'react-scripts' | grep -v grep | awk '{print $2}' | xargs kill -9 cd "$root_path" - npm set registry "$original_npm_registry_url" - yarn config set registry "$original_yarn_registry_url" + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + stopLocalRegistry } # Error messages are redirected to stderr @@ -75,18 +73,8 @@ yarn # First, publish the monorepo. # ****************************************************************************** -# Start local registry -tmp_registry_log=`mktemp` -(cd && nohup npx verdaccio@3.8.2 -c "$root_path"/tasks/verdaccio.yaml &>$tmp_registry_log &) -# Wait for `verdaccio` to boot -grep -q 'http address' <(tail -f $tmp_registry_log) - -# Set registry to local registry -npm set registry "$custom_registry_url" -yarn config set registry "$custom_registry_url" - -# Login so we can publish packages -(cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +# Start the local NPM registry +startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Publish the monorepo git clean -df diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 07a5ddb3984..d31858d2ade 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -15,17 +15,16 @@ cd "$(dirname "$0")" # CLI and app temporary locations # http://unix.stackexchange.com/a/84980 temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` -custom_registry_url=http://localhost:4873 -original_npm_registry_url=`npm get registry` -original_yarn_registry_url=`yarn config get registry` + +# Load functions for working with local NPM registry (Verdaccio) +source local-registry.sh function cleanup { echo 'Cleaning up.' - ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 cd "$root_path" rm -rf "$temp_app_path" - npm set registry "$original_npm_registry_url" - yarn config set registry "$original_yarn_registry_url" + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + stopLocalRegistry } # Error messages are redirected to stderr @@ -96,18 +95,8 @@ yarn # First, publish the monorepo. # ****************************************************************************** -# Start local registry -tmp_registry_log=`mktemp` -(cd && nohup npx verdaccio@3.8.2 -c "$root_path"/tasks/verdaccio.yaml &>$tmp_registry_log &) -# Wait for `verdaccio` to boot -grep -q 'http address' <(tail -f $tmp_registry_log) - -# Set registry to local registry -npm set registry "$custom_registry_url" -yarn config set registry "$custom_registry_url" - -# Login so we can publish packages -(cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +# Start the local NPM registry +startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Publish the monorepo git clean -df diff --git a/tasks/e2e-kitchensink-eject.sh b/tasks/e2e-kitchensink-eject.sh index 6425b890e8e..d614a767d7e 100755 --- a/tasks/e2e-kitchensink-eject.sh +++ b/tasks/e2e-kitchensink-eject.sh @@ -16,20 +16,19 @@ cd "$(dirname "$0")" # http://unix.stackexchange.com/a/84980 temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` temp_module_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_module_path'` -custom_registry_url=http://localhost:4873 -original_npm_registry_url=`npm get registry` -original_yarn_registry_url=`yarn config get registry` + +# Load functions for working with local NPM registry (Verdaccio) +source local-registry.sh function cleanup { echo 'Cleaning up.' unset BROWSERSLIST - ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 ps -ef | grep 'react-scripts' | grep -v grep | awk '{print $2}' | xargs kill -9 cd "$root_path" # TODO: fix "Device or resource busy" and remove ``|| $CI` rm -rf "$temp_app_path" "$temp_module_path" || $CI - npm set registry "$original_npm_registry_url" - yarn config set registry "$original_yarn_registry_url" + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + stopLocalRegistry } # Error messages are redirected to stderr @@ -78,18 +77,8 @@ yarn # First, publish the monorepo. # ****************************************************************************** -# Start local registry -tmp_registry_log=`mktemp` -(cd && nohup npx verdaccio@3.8.2 -c "$root_path"/tasks/verdaccio.yaml &>$tmp_registry_log &) -# Wait for `verdaccio` to boot -grep -q 'http address' <(tail -f $tmp_registry_log) - -# Set registry to local registry -npm set registry "$custom_registry_url" -yarn config set registry "$custom_registry_url" - -# Login so we can publish packages -(cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +# Start the local NPM registry +startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Publish the monorepo git clean -df diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh index 556712d3ec6..dfb2527e22f 100755 --- a/tasks/e2e-kitchensink.sh +++ b/tasks/e2e-kitchensink.sh @@ -16,20 +16,19 @@ cd "$(dirname "$0")" # http://unix.stackexchange.com/a/84980 temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` temp_module_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_module_path'` -custom_registry_url=http://localhost:4873 -original_npm_registry_url=`npm get registry` -original_yarn_registry_url=`yarn config get registry` + +# Load functions for working with local NPM registry (Verdaccio) +source local-registry.sh function cleanup { echo 'Cleaning up.' unset BROWSERSLIST - ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 ps -ef | grep 'react-scripts' | grep -v grep | awk '{print $2}' | xargs kill -9 cd "$root_path" # TODO: fix "Device or resource busy" and remove ``|| $CI` rm -rf "$temp_app_path" "$temp_module_path" || $CI - npm set registry "$original_npm_registry_url" - yarn config set registry "$original_yarn_registry_url" + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + stopLocalRegistry } # Error messages are redirected to stderr @@ -78,18 +77,8 @@ yarn # First, publish the monorepo. # ****************************************************************************** -# Start local registry -tmp_registry_log=`mktemp` -(cd && nohup npx verdaccio@3.8.2 -c "$root_path"/tasks/verdaccio.yaml &>$tmp_registry_log &) -# Wait for `verdaccio` to boot -grep -q 'http address' <(tail -f $tmp_registry_log) - -# Set registry to local registry -npm set registry "$custom_registry_url" -yarn config set registry "$custom_registry_url" - -# Login so we can publish packages -(cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +# Start the local NPM registry +startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Publish the monorepo git clean -df diff --git a/tasks/e2e-simple.sh b/tasks/e2e-simple.sh index 2b8345d1282..bf37a665901 100755 --- a/tasks/e2e-simple.sh +++ b/tasks/e2e-simple.sh @@ -15,19 +15,18 @@ cd "$(dirname "$0")" # App temporary location # http://unix.stackexchange.com/a/84980 temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'` -custom_registry_url=http://localhost:4873 -original_npm_registry_url=`npm get registry` -original_yarn_registry_url=`yarn config get registry` + +# Load functions for working with local NPM registry (Verdaccio) +source local-registry.sh function cleanup { echo 'Cleaning up.' - ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 cd "$root_path" # Uncomment when snapshot testing is enabled by default: # rm ./packages/react-scripts/template/src/__snapshots__/App.test.js.snap rm -rf "$temp_app_path" - npm set registry "$original_npm_registry_url" - yarn config set registry "$original_yarn_registry_url" + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + stopLocalRegistry } # Error messages are redirected to stderr @@ -85,18 +84,8 @@ fi # Bootstrap monorepo yarn -# Start local registry -tmp_registry_log=`mktemp` -(cd && nohup npx verdaccio@3.8.2 -c "$root_path"/tasks/verdaccio.yaml &>$tmp_registry_log &) -# Wait for `verdaccio` to boot -grep -q 'http address' <(tail -f $tmp_registry_log) - -# Set registry to local registry -npm set registry "$custom_registry_url" -yarn config set registry "$custom_registry_url" - -# Login so we can publish packages -(cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +# Start the local NPM registry +startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Lint own code ./node_modules/.bin/eslint --max-warnings 0 packages/babel-preset-react-app/ @@ -270,6 +259,10 @@ verify_module_scope # Eject... echo yes | npm run eject +# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099 +rm yarn.lock +yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self + # Test ejected files were staged test -n "$(git diff --staged --name-only)" diff --git a/tasks/local-registry.sh b/tasks/local-registry.sh new file mode 100644 index 00000000000..26cf896bf43 --- /dev/null +++ b/tasks/local-registry.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +custom_registry_url=http://localhost:4873 +original_npm_registry_url=`npm get registry` +original_yarn_registry_url=`yarn config get registry` +default_verdaccio_package=verdaccio@3.8.2 + +function startLocalRegistry { + # Start local registry + tmp_registry_log=`mktemp` + echo "Registry output file: $tmp_registry_log" + (cd && nohup npx ${VERDACCIO_PACKAGE:-$default_verdaccio_package} -c $1 &>$tmp_registry_log &) + # Wait for Verdaccio to boot + grep -q 'http address' <(tail -f $tmp_registry_log) + + # Set registry to local registry + npm set registry "$custom_registry_url" + yarn config set registry "$custom_registry_url" + + # Login so we can publish packages + (cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$custom_registry_url") +} + +function stopLocalRegistry { + # Restore the original NPM and Yarn registry URLs and stop Verdaccio + npm set registry "$original_npm_registry_url" + yarn config set registry "$original_yarn_registry_url" + + # Kill Verdaccio process + ps -ef | grep 'verdaccio' | grep -v grep | awk '{print $2}' | xargs kill -9 +} diff --git a/tasks/publish.sh b/tasks/publish.sh index 802d10cf518..41c7817faa3 100755 --- a/tasks/publish.sh +++ b/tasks/publish.sh @@ -31,6 +31,7 @@ if [ -z $CI ]; then fi if [ -n "$(git status --porcelain)" ]; then + echo "$(git diff)" echo "Your git status is not clean. Aborting."; exit 1; fi diff --git a/tasks/verdaccio.yaml b/tasks/verdaccio.yaml index e98643b7b76..cbca71cae19 100644 --- a/tasks/verdaccio.yaml +++ b/tasks/verdaccio.yaml @@ -20,6 +20,13 @@ auth: uplinks: npmjs: url: https://registry.npmjs.org/ + max_fails: 40 + maxage: 30m + timeout: 60s + agent_options: + keepAlive: true + maxSockets: 40 + maxFreeSockets: 10 packages: '@*/*': @@ -45,5 +52,9 @@ packages: # log settings logs: - - {type: stdout, format: pretty, level: http} + - {type: stdout, format: pretty, level: warn} #- {type: file, path: verdaccio.log, level: info} + +# See https://github.com/verdaccio/verdaccio/issues/301 +server: + keepAliveTimeout: 0 diff --git a/test/fixtures/__shared__/util/scripts.js b/test/fixtures/__shared__/util/scripts.js index b1ee60e7be8..d1799d18bbd 100644 --- a/test/fixtures/__shared__/util/scripts.js +++ b/test/fixtures/__shared__/util/scripts.js @@ -33,9 +33,9 @@ function execaSafe(...args) { stderr: stripYarn( stripAnsi( err.message - .split(os.EOL) + .split('\n') .slice(2) - .join(os.EOL) + .join('\n') ) ), })); diff --git a/test/fixtures/__shared__/util/setup.js b/test/fixtures/__shared__/util/setup.js index 8dd7d2e3e84..96021d014fa 100644 --- a/test/fixtures/__shared__/util/setup.js +++ b/test/fixtures/__shared__/util/setup.js @@ -96,7 +96,15 @@ module.exports = class TestSetup { async teardown() { if (this.testDirectory != null) { - await fs.remove(this.testDirectory); + try { + await fs.remove(this.testDirectory); + } catch (ex) { + if (this.isLocal) { + throw ex; + } else { + // In CI, don't worry if the test directory was not able to be deleted + } + } this.testDirectory = null; this._scripts = null; } diff --git a/test/fixtures/webpack-message-formatting/index.test.js b/test/fixtures/webpack-message-formatting/index.test.js index 1aebc3a2175..f102b1cf381 100644 --- a/test/fixtures/webpack-message-formatting/index.test.js +++ b/test/fixtures/webpack-message-formatting/index.test.js @@ -59,7 +59,10 @@ test('formats missing package', async () => { path.join(testSetup.testDirectory, 'src', 'App.js') ); - const { stdout, stderr } = await testSetup.scripts.build(); + let { stdout, stderr } = await testSetup.scripts.build(); + if (process.platform === 'win32') { + stderr = stderr.replace('.\\src\\App.js', './src/App.js'); + } expect({ stdout, stderr }).toMatchSnapshot(); }); @@ -103,7 +106,12 @@ test('formats file not found error', async () => { path.join(testSetup.testDirectory, 'src', 'App.js') ); - const { stdout, stderr } = await testSetup.scripts.build(); + let { stdout, stderr } = await testSetup.scripts.build(); + if (process.platform === 'win32') { + stderr = stderr + .replace('.\\src\\App.js', './src/App.js') + .replace('.\\src', './src'); + } expect({ stdout, stderr }).toMatchSnapshot(); }); @@ -131,6 +139,9 @@ test('formats out of scope error', async () => { path.join(testSetup.testDirectory, 'src', 'App.js') ); - const { stdout, stderr } = await testSetup.scripts.build(); + let { stdout, stderr } = await testSetup.scripts.build(); + if (process.platform === 'win32') { + stderr = stderr.replace('.\\src\\App.js', './src/App.js'); + } expect({ stdout, stderr }).toMatchSnapshot(); });