diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d48ec13fa1..5ea5e87218c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ aliases: - &environment docker: # specify the version you desire here - - image: circleci/node:8.9.0 + - image: circleci/node:12.16.1 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images @@ -92,3 +92,6 @@ workflows: - master jobs: - e2etest + +experimental: + pipelines: true \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index fa97ecedc28..66df3b7ab2d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -8.9 +12.16.1 diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 64635b7fc03..dac50593d6e 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -15,12 +15,15 @@ For modules and core platform updates, the initial reviewer should request an ad - If the change is a new feature / change to core prebid.js - review the change with a Tech Lead on the project and make sure they agree with the nature of change. - If the change results in needing updates to docs (such as public API change, module interface etc), add a label for "needs docs" and inform the submitter they must submit a docs PR to update the appropriate area of Prebid.org **before the PR can merge**. Help them with finding where the docs are located on prebid.org if needed. - Below are some examples of bidder specific updates that should require docs update (in their dev-docs/bidders/bidder.md file): - - Add support for GDPR consentManagement module > add `gdpr_supported: true` - - Add support for US Privacy consentManagement module > add `usp_supported: true` - - Add support for userId module > add `userId: pubCommon, digitrust, newProviderHere` - - Add support for video and/or native mediaTypes > add `media_types: video, native` - - Add support for COPPA > add `coppa_supported: true` - - Add support for SChain > add `schain_supported: true` + - If they support the GDPR consentManagement module and TCF1, add `gdpr_supported: true` + - If they support the GDPR consentManagement module and TCF2, add `tcf2_supported: true` + - If they support the US Privacy consentManagementUsp module, add `usp_supported: true` + - If they support one or more userId modules, add `userId: (list of supported vendors)` + - If they support video and/or native mediaTypes add `media_types: video, native`. Note that display is added by default. If you don't support display, add "no-display" as the first entry, e.g. `media_types: no-display, native` + - If they support COPPA, add `coppa_supported: true` + - If they support SChain, add `schain_supported: true` + - If their bidder doesn't work well with safeframed creatives, add `safeframes_ok: false`. This will alert publishers to not use safeframed creatives when creating the ad server entries for their bidder. + - If they're a member of Prebid.org, add `prebid_member: true` - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. @@ -46,11 +49,16 @@ For modules and core platform updates, the initial reviewer should request an ad ## Ticket Coordinator -Each week, Prebid Org assigns one person to keep an eye on incoming issues and PRs. That person should: +Each week, Prebid Org assigns one person to keep an eye on incoming issues and PRs. Every Monday morning a reminder is +sent to the prebid-js slack channel with a link to the spreadsheet. If you're on rotation, please check that list each +Monday to see if you're on-duty. + +When on-duty: - Review issues and PRs at least once per weekday for new items. Encourage a 48 "SLA" on PRs/issues assigned. Aim for touchpoint once every 48/hours. -- For PRs: assign PRs to individuals on the PR review list. Try to be equitable -- not all PRs are created equally. Use the "Assigned" field and add the "Needs Review" label. +- For PRs: assign PRs to individuals on the **PR review list**. Try to be equitable -- not all PRs are created equally. Use the "Assigned" field and add the "Needs Review" label. - For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. Please add labels as appropriate (I.E. bug, question, backlog etc). - Issues that are questions or troubleshooting requests may be closed if the originator doesn't respond within a week to requests for confirmation or details. - Issues that are bug reports should be left open and assigned to someone in PR rotation to confirm or deny the bug status. -- It's polite to check with others before assigning them large tasks. -- If possible, check in on older items and see if they can be unstuck. +- It's polite to check with others before assigning them extra-large tasks. +- If possible, check in on older PRs and Issues and see if they can be unstuck. +- Perform the weekly Prebid.js release per instructions at https://github.com/prebid/Prebid.js/blob/master/RELEASE_SCHEDULE.md . This generally takes place on Tues or Weds. diff --git a/README.md b/README.md index 0e07521ac3b..0dd5b25a50f 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ prebid.requestBids({ $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 8.9.x or greater installed. +*Note:* You need to have `NodeJS` 12.16.1 or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To comply with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in its setup. diff --git a/allowedModules.js b/allowedModules.js index 4f8b8039d97..2a521f781f9 100644 --- a/allowedModules.js +++ b/allowedModules.js @@ -1,11 +1,11 @@ const sharedWhiteList = [ - 'core-js/library/fn/array/find', // no ie11 - 'core-js/library/fn/array/includes', // no ie11 - 'core-js/library/fn/set', // ie11 supports Set but not Set#values - 'core-js/library/fn/string/includes', // no ie11 - 'core-js/library/fn/number/is-integer', // no ie11, - 'core-js/library/fn/array/from' // no ie11 + 'core-js-pure/features/array/find', // no ie11 + 'core-js-pure/features/array/includes', // no ie11 + 'core-js-pure/features/set', // ie11 supports Set but not Set#values + 'core-js-pure/features/string/includes', // no ie11 + 'core-js-pure/features/number/is-integer', // no ie11, + 'core-js-pure/features/array/from' // no ie11 ]; module.exports = { diff --git a/gulpHelpers.js b/gulpHelpers.js index aabd28ced02..bcaf3736f15 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -84,7 +84,9 @@ module.exports = { if (fs.lstatSync(modulePath).isDirectory()) { modulePath = path.join(modulePath, 'index.js') } - memo[modulePath] = moduleName; + if (fs.existsSync(modulePath)) { + memo[modulePath] = moduleName; + } return memo; }, {}); } catch (err) { diff --git a/gulpfile.js b/gulpfile.js index 1b5cd85abd6..64152baa7ba 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ 'use strict'; var _ = require('lodash'); @@ -32,8 +33,8 @@ var prebid = require('./package.json'); var dateString = 'Updated : ' + (new Date()).toISOString().substring(0, 10); var banner = '/* <%= prebid.name %> v<%= prebid.version %>\n' + dateString + ' */\n'; var port = 9999; -const mockServerPort = 4444; -const host = argv.host ? argv.host : 'localhost'; +const FAKE_SERVER_HOST = argv.host ? argv.host : 'localhost'; +const FAKE_SERVER_PORT = 4444; const { spawn } = require('child_process'); // these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules @@ -238,25 +239,25 @@ function test(done) { ]; } - //run mock-server - const mockServer = spawn('node', ['./test/mock-server/index.js', '--port=' + mockServerPort]); - mockServer.stdout.on('data', (data) => { + // run fake-server + const fakeServer = spawn('node', ['./test/fake-server/index.js', `--port=${FAKE_SERVER_PORT}`]); + fakeServer.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); - mockServer.stderr.on('data', (data) => { + fakeServer.stderr.on('data', (data) => { console.log(`stderr: ${data}`); }); execa(wdioCmd, wdioOpts, { stdio: 'inherit' }) .then(stdout => { - // kill mock server - mockServer.kill('SIGINT'); + // kill fake server + fakeServer.kill('SIGINT'); done(); process.exit(0); }) .catch(err => { - // kill mock server - mockServer.kill('SIGINT'); + // kill fake server + fakeServer.kill('SIGINT'); done(new Error(`Tests failed with error: ${err}`)); process.exit(1); }); @@ -326,11 +327,27 @@ function setupE2e(done) { done(); } -gulp.task('updatepath', function () { +function injectFakeServerEndpoint() { return gulp.src(['build/dist/*.js']) - .pipe(replace('https://ib.adnxs.com/ut/v3/prebid', 'http://' + host + ':' + mockServerPort + '/')) + .pipe(replace('https://ib.adnxs.com/ut/v3/prebid', `http://${FAKE_SERVER_HOST}:${FAKE_SERVER_PORT}`)) .pipe(gulp.dest('build/dist')); -}); +} + +function injectFakeServerEndpointDev() { + return gulp.src(['build/dev/*.js']) + .pipe(replace('https://ib.adnxs.com/ut/v3/prebid', `http://${FAKE_SERVER_HOST}:${FAKE_SERVER_PORT}`)) + .pipe(gulp.dest('build/dev')); +} + +function startFakeServer() { + const fakeServer = spawn('node', ['./test/fake-server/index.js', `--port=${FAKE_SERVER_PORT}`]); + fakeServer.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + fakeServer.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + }); +} // support tasks gulp.task(lint); @@ -355,9 +372,12 @@ gulp.task('build', gulp.series(clean, 'build-bundle-prod')); gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); gulp.task('serve', gulp.series(clean, lint, gulp.parallel('build-bundle-dev', watch, test))); +gulp.task('serve-fast', gulp.series(clean, gulp.parallel('build-bundle-dev', watch))); +gulp.task('serve-fake', gulp.series(clean, gulp.parallel('build-bundle-dev', watch), injectFakeServerEndpointDev, test, startFakeServer)); + gulp.task('default', gulp.series(clean, makeWebpackPkg)); -gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-prod', watch), 'updatepath', test)); +gulp.task('e2e-test', gulp.series(clean, setupE2e, gulp.parallel('build-bundle-prod', watch), injectFakeServerEndpoint, test)); // other tasks gulp.task(bundleToStdout); gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step diff --git a/integrationExamples/gpt/responsiveAds_sizeMappingV2.html b/integrationExamples/gpt/advanced_size_mapping.html similarity index 62% rename from integrationExamples/gpt/responsiveAds_sizeMappingV2.html rename to integrationExamples/gpt/advanced_size_mapping.html index d262af5199a..4f1ba085c77 100644 --- a/integrationExamples/gpt/responsiveAds_sizeMappingV2.html +++ b/integrationExamples/gpt/advanced_size_mapping.html @@ -1,3 +1,6 @@ + + @@ -8,15 +11,16 @@ const FAILSAFE_TIMEOUT = 3300; const PREBID_TIMEOUT = 1000; + // Example of a multi-format ad unit setup with uses the module `sizeMappingV2.js`. const adUnits = [{ code: 'div-gpt-ad-1460505748561-0', mediaTypes: { banner: { sizeConfig: [ { minViewPort: [0, 0], sizes: [] }, // remove if < 750px - { minViewPort: [750, 0], sizes: [[300, 250], [300, 600]] }, // between 750px and 1199px - { minViewPort: [1200, 0], sizes: [[970, 90], [728, 90], [300, 250]] }, // between 1200px and 1599px - { minViewPort: [1600, 0], sizes: [[1000, 300], [970, 90], [728, 90], [300, 250]] } // greater than 1600px + { minViewPort: [750, 0], sizes: [[300, 250], [300, 600]] }, // between 750px and 1199px, use sizes: [[300, 250], [300, 600]] + { minViewPort: [1200, 0], sizes: [[970, 90], [728, 90], [300, 250]] }, // between 1200px and 1599px, use sizes: [[970, 90], [728, 90], [300, 250]] + { minViewPort: [1600, 0], sizes: [[1000, 300], [970, 90], [728, 90], [300, 250]] } // greater than 1600px, use sizes: [[1000, 300], [970, 90], [728, 90], [300, 250]] ] }, video: { @@ -31,9 +35,9 @@ required: true, sizes: [150, 50] }, - + // native media type enters auction only if device width is > 600px sizeConfig: [ - { minViewPort: [0, 0], active: false }, + { minViewPort: [0, 0], active: false }, { minViewPort: [600, 0], active: true } ] } @@ -54,12 +58,33 @@ siteId: 70608, zoneId: 498816 }, + // example of a bidder level size config. In the scenario below, bidder 'rubicon' enters auction only if the device width + // is between 850-1200 and it'll only send request for the 'native' media type. sizeConfig: [ { minViewPort: [0, 0], relevantMediaTypes: ['none'] }, { minViewPort: [850, 0], relevantMediaTypes: ['native'] }, { minViewPort: [1200, 0], relevantMediaTypes: ['none'] } ] }] + }, { + // Example of an 'Identical Ad Unit' (same 'code' as previous ad unit but different 'mediaTypes' object) + // Ad Unit makes use of the 'labelAll' operator. (the label operators can be applied at the bidder lever as well) + code: 'div-gpt-ad-1460505748561-0', + labelAll: ['tablet'], // Label check fails since labels passed to pbjs.requestBids() equals ['mobile']. This disables the entire ad unit. + mediaTypes: { + banner: { + sizeConfig: [ + { minViewPort: [800, 0], sizes: [[360, 400], [640, 200]] }, + { minViewPort: [1000, 0], sizes: [] } + ] + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 4232323 + } + }] }]; var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; @@ -75,9 +100,11 @@ pbjs.que.push(function () { pbjs.addAdUnits(adUnits); + pbjs.setConfig({debug: true}); pbjs.requestBids({ bidsBackHandler: sendAdserverRequest, - timeout: PREBID_TIMEOUT + timeout: PREBID_TIMEOUT, + labels: ['mobile'] }); }); diff --git a/integrationExamples/gpt/audienceNetwork_dfp.html b/integrationExamples/gpt/audienceNetwork_dfp.html deleted file mode 100644 index b30df31b276..00000000000 --- a/integrationExamples/gpt/audienceNetwork_dfp.html +++ /dev/null @@ -1,83 +0,0 @@ - -
- - - - -Audience Network quick start
-