diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2de40b8fb6385c94d1f2ce33b7fea91ba9d7280..e23ce3260daf84b4059fc6b0554b2f88eef56956 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,6 +24,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] node-version: [10, 12] python-version: [3.8] + java-version: [11] exclude: - os: windows-latest node-version: 10 @@ -39,14 +40,14 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Set up Java 11 - if: matrix.os == 'ubuntu-latest' && matrix.node-version == 12 && github.ref != 'refs/heads/master' + - name: Set up Java ${{ matrix.java-version }} + if: matrix.node-version == 12 && github.ref != 'refs/heads/master' uses: actions/setup-java@v1 with: - java-version: 11 + java-version: ${{ matrix.java-version }} - name: Skip Java tests - if: matrix.os != 'ubuntu-latest' || matrix.node-version != 12 || github.ref == 'refs/heads/master' + if: matrix.node-version != 12 || github.ref == 'refs/heads/master' run: echo "::set-env name=SKIP_JAVA_TESTS::true" - name: Init platform diff --git a/docs/development/local-development.md b/docs/development/local-development.md index 5e71d27a4a1106746266b0cfa64d5c4744a77376..1c3bfa435a77c7915699d6eb81c89220d704d10f 100644 --- a/docs/development/local-development.md +++ b/docs/development/local-development.md @@ -15,16 +15,20 @@ and `exports`. We will transpile them to `commonjs` on build. #### Prerequisites -For local development some dependencies are required. +For local development some dependencies are required: - git - nodejs `^10.13.0 || ^12.0.0` - yarn `^1.17.0` - c++ compiler - python `^2.7` with `mock` library +- java between `8` and `12` Python 2.7 is required in development in order to support installing with `node-gyp`, which does not yet support Python 3. `mock` is used by Renovate in production and is now part of the Python standard library, but only from 3.3 onwards. +Java is required to execute Gradle in tests. +If you don’t have Java installed, the respective tests will be skipped. + _Linux_ You can use the following commands for `Ubuntu`. @@ -34,9 +38,11 @@ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update -sudo apt-get install -y git python-minimal build-essential nodejs yarn +sudo apt-get install -y git python-minimal build-essential nodejs yarn default-jre-headless ``` +You can also use [SDKMAN](https://sdkman.io/) to manage Java versions. + _Windows_ The following steps work to set up a brand new Windows 10 installation for developing Renovate. If you already have some components installed, you can naturally skip them. @@ -46,11 +52,11 @@ The following steps work to set up a brand new Windows 10 installation for devel - In an Administrator PowerShell prompt, run `npm install -global npm` and then `npm --add-python-to-path='true' --debug install --global windows-build-tools` - Install [Yarn](https://yarnpkg.com/lang/en/docs/install/#windows-stable) - Install `mock` for Python: - - `curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py` - `python get-pip.py` - `rm get-pip.py` - `python -m pip install mock` +- Install Java, e.g. from [AdoptOpenJDK](https://adoptopenjdk.net/?variant=openjdk11) or any other distribution Verify you have everything installed with appropriate versions, e.g.: @@ -65,6 +71,10 @@ The following steps work to set up a brand new Windows 10 installation for devel Python 2.7.16 PS C:\Windows\system32> python -c "import mock; print(mock.__version__)" 3.0.5 + PS C:\Windows\system32> java -version + openjdk version "11.0.6" 2020-01-14 + OpenJDK Runtime Environment 18.9 (build 11.0.6+10) + OpenJDK 64-Bit Server VM 18.9 (build 11.0.6+10, mixed mode) ``` #### Fork and Clone diff --git a/lib/manager/gradle/gradle-updates-report.spec.ts b/lib/manager/gradle/gradle-updates-report.spec.ts index 99d41ab438d3b79a37bc04963615b75eff4c8b09..3821be826890b3e665fb42d035563c4345a7562f 100644 --- a/lib/manager/gradle/gradle-updates-report.spec.ts +++ b/lib/manager/gradle/gradle-updates-report.spec.ts @@ -1,6 +1,7 @@ import tmp, { DirectoryResult } from 'tmp-promise'; import * as fs from 'fs-extra'; import * as path from 'path'; +import { spawnSync, SpawnSyncReturns } from 'child_process'; import { exec } from '../../util/exec'; import { GRADLE_DEPENDENCY_REPORT_OPTIONS } from './index'; import { @@ -9,13 +10,16 @@ import { } from './gradle-updates-report'; const fixtures = 'lib/manager/gradle/__fixtures__'; -const skipJavaTestsEnv = 'SKIP_JAVA_TESTS'; +const failIfNoJavaEnv = 'CI'; const gradleJavaVersionSupport = { 5: { min: 8, max: 12 }, 6: { min: 8, max: 13 }, }; +const skipJava = process.env.SKIP_JAVA_TESTS === 'true'; +const enforceJava = process.env[failIfNoJavaEnv] === 'true' && !skipJava; + function parseJavaVersion(javaVersionOutput: string) { const versionMatch = /version "(?:1\.)?(\d+)[\d._-]*"/.exec( javaVersionOutput @@ -23,61 +27,78 @@ function parseJavaVersion(javaVersionOutput: string) { if (versionMatch !== null && versionMatch.length === 2) { return parseInt(versionMatch[1], 10); } + if (enforceJava) + throw Error(`This test suite needs Java and ${failIfNoJavaEnv} is set. However, we cannot parse the Java version. +The output of java -version was: +${javaVersionOutput}`); return 0; } +function determineJavaVersion(): number { + let javaVersionCommand: SpawnSyncReturns<string>; + let error: Error; + try { + javaVersionCommand = spawnSync('java', ['-version'], { + encoding: 'utf8', + windowsHide: true, + }); + } catch (e) { + error = e; + } + if (javaVersionCommand.error) error = javaVersionCommand.error; + if (error) { + if (!enforceJava) return 0; + throw Error( + `This test suite needs Java and ${failIfNoJavaEnv} is set. +Result of java -version: +${error}` + ); + } + return parseJavaVersion(javaVersionCommand.stderr); +} + describe('lib/manager/gradle/gradle-updates-report', () => { let workingDir: DirectoryResult; - let javaVersion: number; - const skipJava = process.env[skipJavaTestsEnv] !== undefined; - - beforeAll(async () => { - javaVersion = await exec('java -version') - .then(({ stderr }) => parseJavaVersion(stderr)) - .catch(reason => { - throw Error( - `This test suite needs Java. Please provide Java or set the environment variable ${skipJavaTestsEnv} to true. -Output of java -version: -${reason}` - ); - }); - }); + const javaVersion = determineJavaVersion(); beforeEach(async () => { workingDir = await tmp.dir({ unsafeCleanup: true }); }); describe('createRenovateGradlePlugin', () => { - (skipJava ? it.skip : it).each([[5], [6]])( - `generates a report for Gradle version %i`, - async (gradleVersion: number) => { - const supportedJavaVersions = gradleJavaVersionSupport[gradleVersion]; - if ( - javaVersion < supportedJavaVersions.min || - javaVersion > supportedJavaVersions.max - ) { - throw Error( - `This test needs a Java version between ${supportedJavaVersions.min} and ${supportedJavaVersions.max}` - ); - } - await fs.copy(`${fixtures}/minimal-project`, workingDir.path); - await fs.copy( - `${fixtures}/gradle-wrappers/${gradleVersion}`, - workingDir.path + for (const gradleVersion of [5, 6]) { + const supportedJavaVersions = gradleJavaVersionSupport[gradleVersion]; + const gradleSupportsThisJavaVersion = + javaVersion >= supportedJavaVersions.min && + javaVersion <= supportedJavaVersions.max; + if (!gradleSupportsThisJavaVersion && enforceJava) + throw Error( + `This test needs a Java version between ${supportedJavaVersions.min} and ${supportedJavaVersions.max}. The current Java version is ${javaVersion} and ${failIfNoJavaEnv} is set!` ); - await createRenovateGradlePlugin(workingDir.path); + (!gradleSupportsThisJavaVersion || skipJava ? it.skip : it)( + `generates a report for Gradle version ${gradleVersion}`, + // the function creation is correct and intended + // eslint-disable-next-line no-loop-func + async () => { + await fs.copy(`${fixtures}/minimal-project`, workingDir.path); + await fs.copy( + `${fixtures}/gradle-wrappers/${gradleVersion}`, + workingDir.path + ); + await createRenovateGradlePlugin(workingDir.path); - const gradlew = path.join(workingDir.path, 'gradlew'); - await exec(`${gradlew} ${GRADLE_DEPENDENCY_REPORT_OPTIONS}`, { - cwd: workingDir.path, - }); - expect( - fs.readJSONSync( - `${workingDir.path}/${GRADLE_DEPENDENCY_REPORT_FILENAME}` - ) - ).toMatchSnapshot(); - }, - 120000 - ); + const gradlew = path.join(workingDir.path, 'gradlew'); + await exec(`${gradlew} ${GRADLE_DEPENDENCY_REPORT_OPTIONS}`, { + cwd: workingDir.path, + }); + expect( + fs.readJSONSync( + `${workingDir.path}/${GRADLE_DEPENDENCY_REPORT_FILENAME}` + ) + ).toMatchSnapshot(); + }, + 120000 + ); + } }); });