From 38ebf5ac9f507bfd9ab1ce27b71339736a3a9c61 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Wed, 13 Jun 2018 16:11:26 -0400 Subject: [PATCH] Run tests on release builds Also, added ability to call VSTS release builds via API. --- .circleci/config.yml | 42 ++++++++++--------- script/ci-release-build.js | 83 +++++++++++++++++++++++++++++++++++++- script/upload.py | 4 +- vsts.yml | 19 ++++++++- 4 files changed, 124 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 57673a49abf4..02e5f89f2b4f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ build-steps: &build-steps command: | if [ -n "${RUN_RELEASE_BUILD}" ]; then echo 'release build triggered from api' - echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV + echo 'export ELECTRON_RELEASE=1 UPLOAD_TO_S3=1' >> $BASH_ENV fi - run: name: Bootstrap @@ -43,10 +43,10 @@ build-steps: &build-steps - run: name: Upload distribution command: | - if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then + if [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" != "1" ]; then echo 'Uploading Electron release distribution to github releases' script/upload.py - elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then + elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" == "1" ]; then echo 'Uploading Electron release distribution to s3' script/upload.py --upload_to_s3 else @@ -55,7 +55,7 @@ build-steps: &build-steps - run: name: Setup for headless testing command: | - if [ "$ELECTRON_RELEASE" != "1" ] && [ "$RUN_HEADLESS_TESTS" == "true" ]; then + if [ "$RUN_HEADLESS_TESTS" == "true" ]; then echo 'Setup for headless testing' sh -e /etc/init.d/xvfb start else @@ -67,30 +67,34 @@ build-steps: &build-steps MOCHA_FILE: junit/test-results.xml MOCHA_REPORTER: mocha-junit-reporter command: | - if [ "$ELECTRON_RELEASE" != "1" ] && [ "$RUN_TESTS" == "true" ]; then - echo 'Testing Electron debug build' - mkdir junit - script/test.py --ci - else - if [ "$ELECTRON_RELEASE" == "1" ]; then - echo 'Skipping testing on release build' + if [ "$RUN_TESTS" == "true" ]; then + if [ "$ELECTRON_RELEASE" != "1" ]; then + echo 'Testing Electron debug build' + mkdir junit + script/test.py --ci --rebuild_native_modules else - echo 'Skipping tests due to configuration' + echo 'Testing Electron release build' + mkdir junit + script/test.py --ci --rebuild_native_modules -c R fi + else + echo 'Skipping tests due to configuration' fi - run: name: Verify FFmpeg command: | - if [ "$ELECTRON_RELEASE" != "1" ] && [ "$RUN_TESTS" == "true" ]; then - echo 'Verifying ffmpeg on debug build' - script/verify-ffmpeg.py - else - if [ "$ELECTRON_RELEASE" == "1" ]; then - echo 'Skipping verify ffmpeg on release build' + if [ "$RUN_TESTS" == "true" ]; then + if [ "$ELECTRON_RELEASE" != "1" ]; then + echo 'Verifying ffmpeg on debug build' + script/verify-ffmpeg.py else - echo 'Skipping tests due to configuration' + echo 'Verifying ffmpeg on release build' + script/verify-ffmpeg.py -R fi + else + echo 'Skipping tests due to configuration' fi + - run: name: Generate Typescript Definitions command: | diff --git a/script/ci-release-build.js b/script/ci-release-build.js index de4574ca1f1e..d543c6d27f00 100644 --- a/script/ci-release-build.js +++ b/script/ci-release-build.js @@ -1,6 +1,7 @@ const assert = require('assert') const request = require('request') const buildAppVeyorURL = 'https://windows-ci.electronjs.org/api/builds' +const vstsURL = 'https://github.visualstudio.com/electron/_apis/build' const circleCIJobs = [ 'electron-linux-arm', @@ -10,6 +11,11 @@ const circleCIJobs = [ 'electron-linux-x64' ] +const vstsJobs = [ + 'electron-release-mas-x64', + 'electron-release-osx-x64' +] + async function makeRequest (requestOptions, parseResponse) { return new Promise((resolve, reject) => { request(requestOptions, (err, res, body) => { @@ -62,7 +68,7 @@ async function circleCIcall (buildUrl, targetBranch, job, options) { }, true).catch(err => { console.log('Error calling CircleCI:', err) }) - console.log(`Check ${circleResponse.build_url} for status. (${job})`) + console.log(`CircleCI release build request for ${job} successful. Check ${circleResponse.build_url} for status.`) } async function buildAppVeyor (targetBranch, options) { @@ -113,6 +119,70 @@ function buildCircleCI (targetBranch, options) { } } +async function buildVSTS (targetBranch, options) { + if (options.job) { + assert(vstsJobs.includes(options.job), `Unknown CI job name: ${options.job}.`) + } + console.log(`Triggering VSTS to run build on branch: ${targetBranch} with release flag.`) + assert(process.env.VSTS_TOKEN, 'VSTS_TOKEN not found in environment') + let environmentVariables = {} + + if (!options.ghRelease) { + environmentVariables.UPLOAD_TO_S3 = 1 + } + + if (options.automaticRelease) { + environmentVariables.AUTO_RELEASE = 'true' + } + + let requestOpts = { + url: `${vstsURL}/definitions?api-version=4.1`, + auth: { + user: '', + password: process.env.VSTS_TOKEN + }, + headers: { + 'Content-Type': 'application/json' + } + } + let vstsResponse = await makeRequest(requestOpts, true).catch(err => { + console.log('Error calling VSTS to get build definitions:', err) + }) + let buildsToRun = [] + if (options.job) { + buildsToRun = vstsResponse.value.filter(build => build.name === options.job) + } else { + buildsToRun = vstsResponse.value.filter(build => vstsJobs.includes(build.name)) + } + buildsToRun.forEach((build) => callVSTSBuild(build, targetBranch, environmentVariables)) +} + +async function callVSTSBuild (build, targetBranch, environmentVariables) { + let buildBody = { + definition: build, + sourceBranch: targetBranch + } + if (Object.keys(environmentVariables).length !== 0) { + buildBody.parameters = JSON.stringify(environmentVariables) + } + let requestOpts = { + url: `${vstsURL}/builds?api-version=4.1`, + auth: { + user: '', + password: process.env.VSTS_TOKEN + }, + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(buildBody), + method: 'POST' + } + let vstsResponse = await makeRequest(requestOpts, true).catch(err => { + console.log(`Error calling VSTS for job ${build.name}`, err) + }) + console.log(`VSTS release build request for ${build.name} successful. Check ${vstsResponse._links.web.href} for status.`) +} + function runRelease (targetBranch, options) { if (options.ci) { switch (options.ci) { @@ -124,10 +194,19 @@ function runRelease (targetBranch, options) { buildAppVeyor(targetBranch, options) break } + case 'VSTS': { + buildVSTS(targetBranch, options) + break + } + default: { + console.log(`Error! Unknown CI: ${options.ci}.`) + process.exit(1) + } } } else { buildCircleCI(targetBranch, options) buildAppVeyor(targetBranch, options) + buildVSTS(targetBranch, options) } } @@ -140,7 +219,7 @@ if (require.main === module) { const targetBranch = args._[0] if (args._.length < 1) { console.log(`Trigger CI to build release builds of electron. - Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor] [--ghRelease] [--automaticRelease] TARGET_BRANCH + Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor|VSTS] [--ghRelease] [--automaticRelease] TARGET_BRANCH `) process.exit(0) } diff --git a/script/upload.py b/script/upload.py index 4a9a107131a2..b188265fc11f 100755 --- a/script/upload.py +++ b/script/upload.py @@ -212,6 +212,7 @@ def create_release_draft(github, tag): def upload_electron(github, release, file_path, args): + filename = os.path.basename(file_path) # if upload_to_s3 is set, skip github upload. if args.upload_to_s3: @@ -221,10 +222,11 @@ def upload_electron(github, release, file_path, args): s3put(bucket, access_key, secret_key, os.path.dirname(file_path), key_prefix, [file_path]) upload_sha256_checksum(release['tag_name'], file_path, key_prefix) + s3url = 'https://gh-contractor-zcbenz.s3.amazonaws.com' + print '{0} uploaded to {1}/{2}/{0}'.format(filename, s3url, key_prefix) return # Delete the original file before uploading in CI. - filename = os.path.basename(file_path) if os.environ.has_key('CI'): try: for asset in release['assets']: diff --git a/vsts.yml b/vsts.yml index a1f2483dbe1d..53ce780e2038 100644 --- a/vsts.yml +++ b/vsts.yml @@ -33,7 +33,7 @@ steps: condition: and(succeeded(), eq(variables['ELECTRON_RELEASE'], '1')) - bash: | - if [ "$TRIGGERED_BY_API" != "1" ]; then + if [ "$UPLOAD_TO_S3" != "1" ]; then echo 'Uploading Electron release distribution to github releases' ELECTRON_S3_BUCKET="$(s3_bucket)" ELECTRON_S3_ACCESS_KEY="$(s3_access_key)" ELECTRON_S3_SECRET_KEY="$(s3_secret_key)" ELECTRON_GITHUB_TOKEN="$(github_token)" script/upload.py else @@ -48,16 +48,31 @@ steps: mkdir junit export MOCHA_FILE="junit/test-results.xml" export MOCHA_REPORTER="mocha-junit-reporter" - script/test.py --ci + script/test.py --ci --rebuild_native_modules name: Test condition: and(succeeded(), ne(variables['ELECTRON_RELEASE'], '1')) +- bash: | + echo 'Testing Electron release build' + mkdir junit + export MOCHA_FILE="junit/test-results.xml" + export MOCHA_REPORTER="mocha-junit-reporter" + script/test.py --ci --rebuild_native_modules -c R + name: Test + condition: and(succeeded(), eq(variables['ELECTRON_RELEASE'], '1')) + - bash: | echo 'Verifying ffmpeg on debug build' script/verify-ffmpeg.py name: Verify_FFmpeg condition: and(succeeded(), ne(variables['ELECTRON_RELEASE'], '1')) +- bash: | + echo 'Verifying ffmpeg on release build' + script/verify-ffmpeg.py -R + name: Verify_FFmpeg + condition: and(succeeded(), eq(variables['ELECTRON_RELEASE'], '1')) + - task: PublishTestResults@2 displayName: Publish Test Results inputs: