diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index e4a736c0b25..96d4f027324 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '20' + node-version: "20" - name: Checkout code uses: actions/checkout@v6 @@ -35,6 +35,9 @@ jobs: - name: Get the diff run: git diff --name-only origin/${{ github.event.pull_request.base.ref }}...refs/remotes/pull/${{ github.event.pull_request.number }}/merge | grep '^\(modules\|src\|libraries\|creative\)/.*\.js$' > __changed_files.txt || true + - name: Get newly added JS files in TS migration paths + run: git diff --name-only --diff-filter=A origin/${{ github.event.pull_request.base.ref }}...refs/remotes/pull/${{ github.event.pull_request.number }}/merge | grep '^\(modules\|src\|libraries\)/.*\.js$' > __new_js_files.txt || true + - name: Run linter on base branch run: npx eslint --no-inline-config --format json $(cat __changed_files.txt | xargs stat --printf '%n\n' 2> /dev/null) > __base.json || true @@ -56,7 +59,7 @@ jobs: const fs = require('fs'); const path = require('path'); const process = require('process'); - + function parse(fn) { return JSON.parse(fs.readFileSync(fn)).reduce((memo, data) => { const file = path.relative(process.cwd(), data.filePath); @@ -67,7 +70,7 @@ jobs: return memo; }, {}) } - + function mkDiff(old, new_) { const files = Object.fromEntries( Object.entries(new_) @@ -83,12 +86,23 @@ jobs: return memo; }, {errors: 0, warnings: 0, files}) } - - function mkComment({errors, warnings, files}) { + + function mkComment({errors, warnings, files}, newJsFiles) { function pl(noun, number) { return noun + (number === 1 ? '' : 's') } - if (errors === 0 && warnings === 0) return; + const comments = []; + + if (newJsFiles.length > 0) { + let jsComment = 'Whoa there partner! This project is migrating to typescript. Consider changing the new JS files to TS, with well-defined types for what interacts with the prebid public API (for example: bid params and configuration). Thanks!\n\n'; + newJsFiles.forEach((file) => { + jsComment += ` * \`${file}\`\n`; + }); + comments.push(jsComment); + } + + if (errors === 0 && warnings === 0) return comments.length > 0 ? comments.join('\n') : undefined; + const summary = []; if (errors) summary.push(`**${errors}** linter ${pl('error', errors)}`) if (warnings) summary.push(`**${warnings}** linter ${pl('warning', warnings)}`) @@ -99,12 +113,18 @@ jobs: if (warnings) summary.push(`+${warnings} ${pl('warning', warnings)}`) cm += ` * \`${file}\` (${summary.join(', ')})\n` }) - return cm; + comments.push(cm); + return comments.join('\n'); + } + + function readLines(fn) { + if (!fs.existsSync(fn)) return []; + return fs.readFileSync(fn, 'utf8').split('\n').map(line => line.trim()).filter(Boolean); } - + const [base, pr] = ['__base.json', '__pr.json'].map(parse); - const comment = mkComment(mkDiff(base, pr)); - + const comment = mkComment(mkDiff(base, pr), readLines('__new_js_files.txt')); + if (comment) { fs.writeFileSync("${{ runner.temp }}/comment.json", JSON.stringify({ issue_number: context.issue.number, diff --git a/AGENTS.md b/AGENTS.md index c340fee56ff..43b12bccf9d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,7 @@ This file contains instructions for the Codex agent and its friends when working ## General guidance - Node.js `>=20` is required; dependencies are managed with `npm`. +- Whenever possible, new modules should provide Typescript types for their public interface. - Added or modified code must have at least 80% unit test coverage. - Link any required documentation PRs in the PR description. - Avoid modifying files in `node_modules` or generated build artifacts under `build`. @@ -48,3 +49,23 @@ This file contains instructions for the Codex agent and its friends when working ## Additional context - for additional context on repo history, consult https://github.com/prebid/github-activity-db/blob/main/CLAUDE.md on how to download and access repo history in a database you can search locally. + +## Common adapter types +- When bid adapter changes need shared type references, look in the core source modules first: +- `src/adapters/bidderFactory.js` for bidder registration/build and bidder-spec wiring concepts. +- `src/userSync.js` for user sync interfaces, sync option handling, and sync registration behavior. +- `src/adapterManager.js` for adapter manager orchestration and type usage patterns around bidder lifecycle. +- Prefer importing or mirroring conventions from these modules instead of redefining local ad-hoc shapes. +- Use imported types for id, analytics, and rtd modules as well whenever possible. +- Always define types for public interface to an adapter, eg each bidder parameter. + +## Review guidelines +- Use the guidelines at PR_REVIEW.md when doing PR reviews. Make all your comments and code suggestions on the PR itself instead of in linked tasks when commenting in a PR review. +- Use the module rules at https://docs.prebid.org/dev-docs/module-rules.html +- Discourage application/json calls, they cause preflight options calls with induced delays over text/plain +- Make sure people are importing from libraries and our methods whenever possible, eg on viewability or accessing navigator +- Bidder params should always only override that information coming on the request; bidders should never make someone specify something that is generally available in an ortb2 field on the request in bidder params unless they need an override. +- Bidders asking for storage access and setting an id in local storage redundant with the shared id is discouraged, they should document why they need to do this odious behavior +- Submodules need to register in submodules.json +- No one should be accessing navigator from vendor modules, if navigator needs to be accessed it should be in a common method or library +- Low priority calls should be import ajax method and use fetch keepalive; they shouldnt use trigger pixel when it can be avoided or fail to specify keepalive. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7a797beeb4..8ff2fd54055 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,9 @@ master branch. Pull requests must have 80% code coverage before being considered for merge. Additional details about the process can be found [here](./PR_REVIEW.md). +Whenever possible, new modules should provide Typescript types for their public interface. +Examples of public interface are bid parameters and configuration (including configuration for analytics, userId, or real time data modules). + There are more details available if you'd like to contribute a [bid adapter](https://docs.prebid.org/dev-docs/bidder-adaptor.html) or [analytics adapter](https://docs.prebid.org/dev-docs/integrate-with-the-prebid-analytics-api.html). ## Issues diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 94fe06c0f0c..75e3e0b35a6 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -19,6 +19,7 @@ General gulp commands include separate commands for serving the codebase on a bu ### General PR review Process +- Whenever possible, new modules should provide Typescript types for their public interface. Examples of public interface are bid parameters and configuration (including configuration for analytics, userId, or real time data modules). - All required global and bidder-adapter rules defined in the [Module Rules](https://docs.prebid.org/dev-docs/module-rules.html) must be followed. Please review these rules often - we depend on reviewers to enforce them. - Checkout the branch (these instructions are available on the GitHub PR page as well). - Verify PR is a single change type. Example, refactor OR bugfix. If more than 1 type, ask submitter to break out requests. diff --git a/eslint.config.js b/eslint.config.js index 90b7313db50..a5310749559 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -202,6 +202,21 @@ module.exports = [ object: 'navigator', message: 'use ajax.js instead' }, + { + property: 'doNotTrack', + object: 'navigator', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, + { + property: 'msDoNotTrack', + object: 'navigator', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, + { + property: 'doNotTrack', + object: 'window', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, ...['outerText', 'innerText'].map(property => ({ property, message: 'use .textContent instead' diff --git a/gulpfile.js b/gulpfile.js index cc543ad73ec..fd1f7f476d6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -540,7 +540,10 @@ gulp.task('update-codeql', function (done) { // npm will by default use .gitignore, so create an .npmignore that is a copy of it except it includes "dist" gulp.task('setup-npmignore', execaTask("sed 's/^\\/\\?dist\\/\\?$//g;w .npmignore' .gitignore", {quiet: true})); gulp.task('build', gulp.series(clean, 'build-bundle-prod', setupDist)); -gulp.task('build-release', gulp.series('update-codeql', 'build', updateCreativeExample, 'update-browserslist', 'setup-npmignore')); +// build for release - in addition to 'build', run tasks that update the codebase to be included in a release commit +gulp.task('build-release', gulp.series('update-codeql', 'build', updateCreativeExample, 'update-browserslist')); +// prepare NPM release - 'build' to generate files in dist/; 'setup-npmignore' to make sure 'dist' is published in NPM +gulp.task('prepare-release', gulp.series('build', 'setup-npmignore')) gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); gulp.task('serve', gulp.series(clean, lint, precompile(), gulp.parallel('build-bundle-dev-no-precomp', watch, test))); diff --git a/integrationExamples/gpt/raveltechRtdProvider_example.html b/integrationExamples/gpt/raveltechRtdProvider_example.html index 8a0be63b6b8..4523ad17ec9 100644 --- a/integrationExamples/gpt/raveltechRtdProvider_example.html +++ b/integrationExamples/gpt/raveltechRtdProvider_example.html @@ -256,9 +256,6 @@ "expires": 28 } }, - { - "name": "quantcastId" - }, { "name": "criteo" }, diff --git a/integrationExamples/gpt/taboola_multiformat.html b/integrationExamples/gpt/taboola_multiformat.html new file mode 100644 index 00000000000..e92d8158fd6 --- /dev/null +++ b/integrationExamples/gpt/taboola_multiformat.html @@ -0,0 +1,492 @@ + + + + +
+ + + + + + + + + + + + + +The multiformat ad unit should generate requests to both endpoints.
+ +Waiting for bids...+ +