From bef6090680a8ee1e3959c5736d78fe9afb6d5d23 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:07:01 -0300 Subject: [PATCH 01/38] DEV: Move test packages to a vm-based ci another take on https://github.com/meteor/meteor/pull/14254 --- .github/workflows/test-packages.yml | 60 +++++++++++++++++ packages/test-in-console/puppeteer_runner.js | 70 ++++++++++++-------- packages/test-in-console/run.sh | 9 ++- 3 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/test-packages.yml diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml new file mode 100644 index 0000000000..37df9004aa --- /dev/null +++ b/.github/workflows/test-packages.yml @@ -0,0 +1,60 @@ +name: Test Packages + +on: + pull_request: + paths: + - "packages/**" + - ".github/workflows/test-packages.yml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test-packages: + runs-on: oss-vm + timeout-minutes: 90 + env: + CXX: g++-12 + TEST_PACKAGES_EXCLUDE: stylus + METEOR_MODERN: true + NODE_ENV: CI + + steps: + - name: Fix workspace permissions + # Self-hosted runners may leave files owned by root from previous runs. + run: sudo chown -R "$(id -un):$(id -gn)" "$GITHUB_WORKSPACE" || true + working-directory: /tmp + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Expose globally-installed puppeteer to Node.js + # puppeteer@23.6.0 is pre-installed on oss-vm via `npm install -g`. + # Setting NODE_PATH lets `require('puppeteer')` resolve it directly, + # so run.sh skips the slow `./meteor npm install -g puppeteer` step. + run: echo "NODE_PATH=$(npm root -g)" >> "$GITHUB_ENV" + + - name: Restore caches + uses: actions/cache@v4 + with: + path: | + ~/.npm + .meteor + .babel-cache + dev_bundle + key: ${{ runner.os }}-meteor-${{ hashFiles('meteor', '**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-meteor- + + - name: Install system dependencies + # g++-12 is needed to build native Node.js add-ons (e.g. fibers). + # All Chromium dependencies are already satisfied on oss-vm. + run: | + if ! dpkg -s g++-12 >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y g++-12 + fi + + - name: Run test-in-console suite + run: ./packages/test-in-console/run.sh diff --git a/packages/test-in-console/puppeteer_runner.js b/packages/test-in-console/puppeteer_runner.js index 7065341278..70d9ebd9f2 100644 --- a/packages/test-in-console/puppeteer_runner.js +++ b/packages/test-in-console/puppeteer_runner.js @@ -1,4 +1,12 @@ -const puppeteer = require('../../dev_bundle/lib/node_modules/puppeteer'); +let puppeteer; +try { + // Prefer the copy bundled inside dev_bundle (local checkout / CI after first run). + puppeteer = require("../../dev_bundle/lib/node_modules/puppeteer"); +} catch (_) { + // Fallback: globally-installed puppeteer (e.g. on oss-vm where it is pre-installed + // via `npm install -g puppeteer@23.6.0` and NODE_PATH is set to `npm root -g`). + puppeteer = require("puppeteer"); +} let testNumber = 0; @@ -9,32 +17,38 @@ async function runNextUrl(browser) { // console.log('PAGE LOG:', msg.text()); // }); - page.on('console', async msg => { + page.on("console", async (msg) => { // this is a way to make sure the travis does not timeout // if the test is running for too long without any output to the console (10 minutes) const text = msg.text(); - if (text.includes('Permissions policy violation')) { + if (text.includes("Permissions policy violation")) { return; } if (text) console.log(text); else { testNumber++; - const currentClientTest = - await page.evaluate(() => __Tinytest._getCurrentRunningTestOnClient()); - if (currentClientTest !== '') { - console.log(`Currently running on the client test: ${ currentClientTest }`) + const currentClientTest = await page.evaluate(() => + __Tinytest._getCurrentRunningTestOnClient() + ); + if (currentClientTest !== "") { + console.log( + `Currently running on the client test: ${currentClientTest}` + ); return; } // If we get here is because we have not yet started the test on the client - const currentServerTest = - await page.evaluate(async () => await __Tinytest._getCurrentRunningTestOnServer()); + const currentServerTest = await page.evaluate( + async () => await __Tinytest._getCurrentRunningTestOnServer() + ); - if (currentServerTest !== '') { - console.log(`Currently running on the server test: ${ currentServerTest }`); + if (currentServerTest !== "") { + console.log( + `Currently running on the server test: ${currentServerTest}` + ); return; } // we were not able to find the name of the test, this is a way to make sure the test is still running - console.log(`Test number: ${ testNumber }`); + console.log(`Test number: ${testNumber}`); } }); @@ -47,12 +61,12 @@ async function runNextUrl(browser) { async function poll() { if (await isDone(page)) { - let failCount = await getFailCount(page); - console.log(`Tests complete with ${ failCount } failures`); - console.log(`Tests complete with ${ await getPassCount(page) } passes`); + const failCount = await getFailCount(page); + console.log(`Tests complete with ${failCount} failures`); + console.log(`Tests complete with ${await getPassCount(page)} passes`); if (failCount > 0) { const failed = await getFailed(page); - failed.map((f) => console.log(`${ f.name } failed: ${ f.info }`)); + failed.map((f) => console.log(`${f.name} failed: ${f.info}`)); await page.close(); await browser.close(); process.exit(1); @@ -76,11 +90,11 @@ async function runNextUrl(browser) { */ async function isDone(page) { return await page.evaluate(function () { - if (typeof TEST_STATUS !== 'undefined') { + if (typeof TEST_STATUS !== "undefined") { return TEST_STATUS.DONE; } - return typeof DONE !== 'undefined' && DONE; + return typeof DONE !== "undefined" && DONE; }); } @@ -91,11 +105,11 @@ async function isDone(page) { */ async function getPassCount(page) { return await page.evaluate(function () { - if (typeof TEST_STATUS !== 'undefined') { + if (typeof TEST_STATUS !== "undefined") { return TEST_STATUS.PASSED; } - return typeof PASSED !== 'undefined' && PASSED; + return typeof PASSED !== "undefined" && PASSED; }); } @@ -106,11 +120,11 @@ async function getPassCount(page) { */ async function getFailCount(page) { return await page.evaluate(function () { - if (typeof TEST_STATUS !== 'undefined') { + if (typeof TEST_STATUS !== "undefined") { return TEST_STATUS.FAILURES; } - return typeof FAILURES !== 'undefined' && FAILURES; + return typeof FAILURES !== "undefined" && FAILURES; }); } @@ -121,10 +135,10 @@ async function getFailCount(page) { */ async function getFailed(page) { return await page.evaluate(function () { - if (typeof TEST_STATUS !== 'undefined') { + if (typeof TEST_STATUS !== "undefined") { return TEST_STATUS.WHERE_FAILED; } - return typeof WHERE_FAILED !== 'undefined' && WHERE_FAILED; + return typeof WHERE_FAILED !== "undefined" && WHERE_FAILED; }); } @@ -134,14 +148,14 @@ async function runTests() { // --no-sandbox and --disable-setuid-sandbox must be disabled for CI compatibility const browser = await puppeteer.launch({ args: [ - '--no-sandbox', - '--disable-setuid-sandbox', - '--disable-web-security', + "--no-sandbox", + "--disable-setuid-sandbox", + "--disable-web-security", ], headless: "new", }); console.log(`Using version: ${await browser.version()}`); - await runNextUrl(browser) + await runNextUrl(browser); } runTests().catch((e) => diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 5a88e9065d..0455fbc02d 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -8,8 +8,13 @@ cd $(dirname $0)/../.. export METEOR_HOME=`pwd` -# Installs into dev_bundle/lib/node_modules/puppeteer. -./meteor npm install -g puppeteer@23.6.0 +# Install puppeteer into dev_bundle only when it is not already available globally +# (e.g. on oss-vm, where puppeteer@23.6.0 is pre-installed via system npm and +# NODE_PATH is set to $(npm root -g) by the CI workflow). +if ! node -e "require('./dev_bundle/lib/node_modules/puppeteer')" 2>/dev/null && \ + ! node -e "require('puppeteer')" 2>/dev/null; then + ./meteor npm install -g puppeteer@23.6.0 +fi export PATH=$METEOR_HOME:$PATH From 7fe60c971c76966b7188a683f4faf5e08cc21bf8 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:26:02 -0300 Subject: [PATCH 02/38] dev: testing something else --- packages/test-in-console/puppeteer_runner.js | 8 +++++++- packages/test-in-console/run.sh | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/test-in-console/puppeteer_runner.js b/packages/test-in-console/puppeteer_runner.js index 70d9ebd9f2..a2e0578489 100644 --- a/packages/test-in-console/puppeteer_runner.js +++ b/packages/test-in-console/puppeteer_runner.js @@ -57,7 +57,13 @@ async function runNextUrl(browser) { return; } - await page.goto(process.env.URL); + // Use domcontentloaded: Meteor apps connect via DDP after DOM parse and never + // fire the default 'load' event in the traditional sense. Increase timeout to + // 120 s to handle slow first-run builds on CI / underpowered machines. + await page.goto(process.env.URL, { + timeout: 120000, + waitUntil: "domcontentloaded", + }); async function poll() { if (await isDone(page)) { diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 0455fbc02d..06d1fed2a3 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -27,6 +27,15 @@ trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT sed '/test-in-console listening$/q' <&3 +# Wait until the HTTP server is actually accepting connections before launching +# Puppeteer. 'test-in-console listening' is emitted by the test driver before +# the HTTP port is fully bound, so a bare goto() would time out on slow starts. +echo "Waiting for test server at $URL..." +until curl --silent --output /dev/null --fail "$URL"; do + sleep 1 +done +echo "Test server is ready." + node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? From be596bb93db9df27bf83281aebf2e69d4581d614 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:35:19 -0300 Subject: [PATCH 03/38] DEV: add recursive --- .github/workflows/test-packages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 37df9004aa..2e53ea62b9 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -28,6 +28,8 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Expose globally-installed puppeteer to Node.js # puppeteer@23.6.0 is pre-installed on oss-vm via `npm install -g`. From 59c7b5aea9e7570254fe3c6685ae23b09a310b63 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:41:20 -0300 Subject: [PATCH 04/38] =?UTF-8?q?DEV:=20it=20works=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-packages.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 2e53ea62b9..f7bc7f985b 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -16,7 +16,6 @@ jobs: timeout-minutes: 90 env: CXX: g++-12 - TEST_PACKAGES_EXCLUDE: stylus METEOR_MODERN: true NODE_ENV: CI @@ -59,4 +58,6 @@ jobs: fi - name: Run test-in-console suite - run: ./packages/test-in-console/run.sh + run: | + export TEST_PACKAGES_EXCLUDE='stylus' + ./packages/test-in-console/run.sh From d13ea22a8095f258b10c97510b17a7a03af57f5c Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:47:24 -0300 Subject: [PATCH 05/38] DEV: it should WORK! --- .github/workflows/test-packages.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index f7bc7f985b..d4845972ac 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -14,10 +14,6 @@ jobs: test-packages: runs-on: oss-vm timeout-minutes: 90 - env: - CXX: g++-12 - METEOR_MODERN: true - NODE_ENV: CI steps: - name: Fix workspace permissions @@ -59,5 +55,12 @@ jobs: - name: Run test-in-console suite run: | - export TEST_PACKAGES_EXCLUDE='stylus' + export TEST_PACKAGES_EXCLUDE="stylus" + export METEOR_MODERN="true" + export NODE_ENV="CI" + export CXX="g++-12" + export phantom="false" + export TIMEOUT_SCALE_FACTOR="20" + export METEOR_HEADLESS="true" + ./packages/test-in-console/run.sh From f8a7e2623cffdbb5c02969d3dd80c4f98757e387 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 21:54:33 -0300 Subject: [PATCH 06/38] DEV: err it should work now! --- .github/workflows/test-packages.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index d4845972ac..caa6cc391f 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -14,6 +14,8 @@ jobs: test-packages: runs-on: oss-vm timeout-minutes: 90 + env: + CXX: g++-12 steps: - name: Fix workspace permissions @@ -62,5 +64,5 @@ jobs: export phantom="false" export TIMEOUT_SCALE_FACTOR="20" export METEOR_HEADLESS="true" - + ./packages/test-in-console/run.sh From ffbd527bc589df60ea59eeded145c221f7be7f1f Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 22:02:59 -0300 Subject: [PATCH 07/38] DEV: remove travis reference --- packages/webapp/socket_file_tests.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/webapp/socket_file_tests.js b/packages/webapp/socket_file_tests.js index 2dbde1927f..19858bd65f 100644 --- a/packages/webapp/socket_file_tests.js +++ b/packages/webapp/socket_file_tests.js @@ -26,6 +26,20 @@ const isMacOS = () => { return platform() === 'darwin'; }; +// Resolve the current process's primary group name by looking up its GID in +// /etc/group. This is used in tests that chown a socket file: we need a group +// the running user actually belongs to, so the chown doesn't fail with EPERM. +const getCurrentGroupName = () => { + try { + const gid = userInfo().gid; + const lines = readFileSync('/etc/group', 'utf8').split('\n'); + const match = lines.find(line => parseInt(line.split(':')[2], 10) === gid); + return match ? match.split(':')[0] : null; + } catch (_) { + return null; + } +}; + const removeTestSocketFile = () => { try { unlinkSync(testSocketFile); @@ -133,7 +147,7 @@ testAsyncMulti( // use UNIX_SOCKET_PATH and UNIX_SOCKET_GROUP const { httpServer, server } = prepareServer(); - const groupToUse = Boolean(process.env.TRAVIS) && 'travis' || (isMacOS() ? 'staff' : 'root'); + const groupToUse = isMacOS() ? 'staff' : (getCurrentGroupName() || 'root'); process.env.UNIX_SOCKET_PATH = testSocketFile; process.env.UNIX_SOCKET_GROUP = groupToUse; process.env.UNIX_SOCKET_PERMISSIONS = '777'; From e5c79bb099f184716cf4e4b422cbdd4689f498a7 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 22:09:54 -0300 Subject: [PATCH 08/38] DEV: lint --- .github/workflows/test-packages.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index caa6cc391f..88305db15f 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -64,5 +64,4 @@ jobs: export phantom="false" export TIMEOUT_SCALE_FACTOR="20" export METEOR_HEADLESS="true" - - ./packages/test-in-console/run.sh + ./packages/test-in-console/run.sh From c4b83550d203c3aaff2b33f8601eee8915fdb848 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 22:40:47 -0300 Subject: [PATCH 09/38] DEV: testing parallel --- .github/workflows/test-packages.yml | 70 ++++++++++++++++++++++++----- packages/test-in-console/run.sh | 20 ++++++++- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 88305db15f..ef31c0f4ac 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -12,10 +12,68 @@ concurrency: jobs: test-packages: + name: "packages / ${{ matrix.group.name }}" runs-on: oss-vm timeout-minutes: 90 env: CXX: g++-12 + METEOR_HOSTED_CI: "true" + + strategy: + fail-fast: false + matrix: + group: + - name: accounts + packages: >- + accounts-base accounts-password accounts-passwordless accounts-2fa + accounts-oauth accounts-ui accounts-ui-unstyled + audit-argument-checks check service-configuration + + - name: auth-social + packages: >- + oauth oauth2 oauth-encryption + accounts-facebook accounts-github accounts-google accounts-twitter + accounts-weibo accounts-meetup accounts-meteor-developer + facebook-oauth github-oauth google-oauth weibo-oauth + meetup-oauth meteor-developer-oauth + facebook-config-ui github-config-ui google-config-ui + twitter-config-ui weibo-config-ui + + - name: database + packages: >- + mongo minimongo allow-deny diff-sequence mongo-id disable-oplog + geojson-utils id-map ordered-dict binary-heap + mongo-livedata npm-mongo npm-mongo-legacy + + - name: ddp-realtime + packages: >- + ddp ddp-client ddp-common ddp-server ddp-rate-limiter + rate-limit inter-process-messaging autoupdate reload + reload-safetybelt routepolicy + + - name: build + packages: >- + babel-compiler babel-runtime ecmascript ecmascript-runtime + ecmascript-runtime-client ecmascript-runtime-server + caching-compiler typescript minifier-css minifier-js + standard-minifier-css static-html-tools es5-shim + constraint-solver package-version-parser + modules modules-runtime modules-runtime-hot + + - name: webapp + packages: >- + webapp webapp-hashing boilerplate-generator + boilerplate-generator-tests hot-code-push server-render + browser-policy browser-policy-common browser-policy-content + browser-policy-framing shell-server force-ssl force-ssl-common + dev-error-overlay react-fast-refresh + + - name: core + packages: >- + meteor core-runtime base64 ejson random tracker reactive-var + reactive-dict callback-hook retry url promise session + dynamic-import localstorage fetch roles facts-base facts-ui + logic-solver insecure autopublish test-helpers rspack steps: - name: Fix workspace permissions @@ -55,13 +113,5 @@ jobs: sudo apt-get install -y g++-12 fi - - name: Run test-in-console suite - run: | - export TEST_PACKAGES_EXCLUDE="stylus" - export METEOR_MODERN="true" - export NODE_ENV="CI" - export CXX="g++-12" - export phantom="false" - export TIMEOUT_SCALE_FACTOR="20" - export METEOR_HEADLESS="true" - ./packages/test-in-console/run.sh + - name: Run tests (${{ matrix.group.name }}) + run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 06d1fed2a3..1f554fb410 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -21,7 +21,25 @@ export PATH=$METEOR_HOME:$PATH export URL='http://127.0.0.1:4096/' export METEOR_PACKAGE_DIRS='packages/deprecated' -exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} $1) +# --- Hosted CI mode --- +# Set METEOR_HOSTED_CI=true to automatically apply CI environment settings and +# exclude Blaze packages (maintained separately at github.com/meteor/blaze) +# and all packages under packages/deprecated/. +if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then + echo "running in hosted CI mode: excluding Blaze and deprecated packages from test run" + export METEOR_MODERN="${METEOR_MODERN:-true}" + export NODE_ENV="${NODE_ENV:-CI}" + export METEOR_HEADLESS="${METEOR_HEADLESS:-true}" + + # Blaze packages — maintained at github.com/meteor/blaze + _BLAZE="blaze,blaze-hot,blaze-html-templates,blaze-tools,caching-html-compiler,html-tools,htmljs,observe-sequence,spacebars,spacebars-compiler,spacebars-tests,templating,templating-compiler,templating-runtime,templating-tools,ui" + # Packages in packages/deprecated/ — kept for backwards compatibility only + _DEPRECATED="amplify,appcache,backbone,code-prettify,context,d3,deps,facebook,facts,fastclick,github,google,handlebars,http,jquery-history,jquery-layout,jquery-waypoints,jsparse,jshint,livedata,markdown,meetup,meteor-developer,meteor-platform,meyerweb-reset,npm-bcrypt,preserve-inputs,showdown,spiderable,srp,standard-app-packages,startup,stylus,twitter,underscore,underscore-tests,weibo" + + export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" +fi + +exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT From 761289035aec98c45cd153075182a228ebe3682a Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 22:52:42 -0300 Subject: [PATCH 10/38] DEV: parallelism MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEV: 🚀 DEV: last parallelism test --- .github/workflows/test-packages.yml | 150 +++++++++++++++++----------- packages/test-in-console/run.sh | 14 +-- 2 files changed, 94 insertions(+), 70 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index ef31c0f4ac..b721a8b3b2 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -12,69 +12,13 @@ concurrency: jobs: test-packages: - name: "packages / ${{ matrix.group.name }}" + name: "Package Tests" runs-on: oss-vm timeout-minutes: 90 env: CXX: g++-12 METEOR_HOSTED_CI: "true" - strategy: - fail-fast: false - matrix: - group: - - name: accounts - packages: >- - accounts-base accounts-password accounts-passwordless accounts-2fa - accounts-oauth accounts-ui accounts-ui-unstyled - audit-argument-checks check service-configuration - - - name: auth-social - packages: >- - oauth oauth2 oauth-encryption - accounts-facebook accounts-github accounts-google accounts-twitter - accounts-weibo accounts-meetup accounts-meteor-developer - facebook-oauth github-oauth google-oauth weibo-oauth - meetup-oauth meteor-developer-oauth - facebook-config-ui github-config-ui google-config-ui - twitter-config-ui weibo-config-ui - - - name: database - packages: >- - mongo minimongo allow-deny diff-sequence mongo-id disable-oplog - geojson-utils id-map ordered-dict binary-heap - mongo-livedata npm-mongo npm-mongo-legacy - - - name: ddp-realtime - packages: >- - ddp ddp-client ddp-common ddp-server ddp-rate-limiter - rate-limit inter-process-messaging autoupdate reload - reload-safetybelt routepolicy - - - name: build - packages: >- - babel-compiler babel-runtime ecmascript ecmascript-runtime - ecmascript-runtime-client ecmascript-runtime-server - caching-compiler typescript minifier-css minifier-js - standard-minifier-css static-html-tools es5-shim - constraint-solver package-version-parser - modules modules-runtime modules-runtime-hot - - - name: webapp - packages: >- - webapp webapp-hashing boilerplate-generator - boilerplate-generator-tests hot-code-push server-render - browser-policy browser-policy-common browser-policy-content - browser-policy-framing shell-server force-ssl force-ssl-common - dev-error-overlay react-fast-refresh - - - name: core - packages: >- - meteor core-runtime base64 ejson random tracker reactive-var - reactive-dict callback-hook retry url promise session - dynamic-import localstorage fetch roles facts-base facts-ui - logic-solver insecure autopublish test-helpers rspack - steps: - name: Fix workspace permissions # Self-hosted runners may leave files owned by root from previous runs. @@ -113,5 +57,93 @@ jobs: sudo apt-get install -y g++-12 fi - - name: Run tests (${{ matrix.group.name }}) - run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} + - name: Run all package groups in parallel + run: | + # Each group runs in a subshell: output is piped through sed to prefix + # every line with "[group]" for real-time readability. The subshell + # exits with run.sh's exit code via ${PIPESTATUS[0]}, so `wait` below + # correctly reflects test failures rather than sed's exit code. + ( + LISTENING_PORT=4101 ./packages/test-in-console/run.sh \ + accounts-base accounts-password accounts-passwordless accounts-2fa \ + accounts-oauth accounts-ui accounts-ui-unstyled \ + audit-argument-checks check service-configuration \ + 2>&1 | sed 's/^/[accounts] /' + exit "${PIPESTATUS[0]}" + ) & pid_accounts=$! + + ( + LISTENING_PORT=4102 ./packages/test-in-console/run.sh \ + oauth oauth2 oauth-encryption \ + accounts-facebook accounts-github accounts-google accounts-twitter \ + accounts-weibo accounts-meetup accounts-meteor-developer \ + facebook-oauth github-oauth google-oauth weibo-oauth \ + meetup-oauth meteor-developer-oauth \ + facebook-config-ui github-config-ui google-config-ui \ + twitter-config-ui weibo-config-ui \ + 2>&1 | sed 's/^/[auth-social] /' + exit "${PIPESTATUS[0]}" + ) & pid_auth_social=$! + + ( + LISTENING_PORT=4103 ./packages/test-in-console/run.sh \ + mongo minimongo allow-deny diff-sequence mongo-id disable-oplog \ + geojson-utils id-map ordered-dict binary-heap \ + mongo-livedata npm-mongo npm-mongo-legacy \ + 2>&1 | sed 's/^/[database] /' + exit "${PIPESTATUS[0]}" + ) & pid_database=$! + + ( + LISTENING_PORT=4104 ./packages/test-in-console/run.sh \ + ddp ddp-client ddp-common ddp-server ddp-rate-limiter \ + rate-limit inter-process-messaging autoupdate reload \ + reload-safetybelt routepolicy \ + 2>&1 | sed 's/^/[ddp-realtime] /' + exit "${PIPESTATUS[0]}" + ) & pid_ddp_realtime=$! + + ( + LISTENING_PORT=4105 ./packages/test-in-console/run.sh \ + babel-compiler babel-runtime ecmascript ecmascript-runtime \ + ecmascript-runtime-client ecmascript-runtime-server \ + caching-compiler typescript minifier-css minifier-js \ + standard-minifier-css static-html-tools es5-shim \ + constraint-solver package-version-parser \ + modules modules-runtime modules-runtime-hot \ + 2>&1 | sed 's/^/[build] /' + exit "${PIPESTATUS[0]}" + ) & pid_build=$! + + ( + LISTENING_PORT=4106 ./packages/test-in-console/run.sh \ + webapp webapp-hashing boilerplate-generator \ + boilerplate-generator-tests hot-code-push server-render \ + browser-policy browser-policy-common browser-policy-content \ + browser-policy-framing shell-server force-ssl force-ssl-common \ + dev-error-overlay react-fast-refresh \ + 2>&1 | sed 's/^/[webapp] /' + exit "${PIPESTATUS[0]}" + ) & pid_webapp=$! + + ( + LISTENING_PORT=4107 ./packages/test-in-console/run.sh \ + meteor core-runtime base64 ejson random tracker reactive-var \ + reactive-dict callback-hook retry url promise session \ + dynamic-import localstorage fetch roles facts-base facts-ui \ + logic-solver insecure autopublish test-helpers rspack \ + 2>&1 | sed 's/^/[core] /' + exit "${PIPESTATUS[0]}" + ) & pid_core=$! + + # Wait for all groups and collect failures. + failed=0 + for group in accounts auth-social database ddp-realtime build webapp core; do + var="pid_${group//-/_}" + wait "${!var}" && status=0 || status=$? + if [ $status -ne 0 ]; then + echo "::error::Group '$group' failed (exit $status)" + failed=1 + fi + done + exit $failed diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 1f554fb410..9dd30a3c5c 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -18,7 +18,8 @@ fi export PATH=$METEOR_HOME:$PATH -export URL='http://127.0.0.1:4096/' +export LISTENING_PORT=${LISTENING_PORT:-4096} +export URL="http://127.0.0.1:${LISTENING_PORT}/" export METEOR_PACKAGE_DIRS='packages/deprecated' # --- Hosted CI mode --- @@ -39,21 +40,12 @@ if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" fi -exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") +exec 3< <(./meteor test-packages --driver-package test-in-console -p $LISTENING_PORT --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT sed '/test-in-console listening$/q' <&3 -# Wait until the HTTP server is actually accepting connections before launching -# Puppeteer. 'test-in-console listening' is emitted by the test driver before -# the HTTP port is fully bound, so a bare goto() would time out on slow starts. -echo "Waiting for test server at $URL..." -until curl --silent --output /dev/null --fail "$URL"; do - sleep 1 -done -echo "Test server is ready." - node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? From 88422e1dbe535883076cf27ce4cc97ac6785754b Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 23:07:04 -0300 Subject: [PATCH 11/38] Revert "DEV: parallelism" This reverts commit 761289035aec98c45cd153075182a228ebe3682a. --- .github/workflows/test-packages.yml | 150 +++++++++++----------------- packages/test-in-console/run.sh | 14 ++- 2 files changed, 70 insertions(+), 94 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index b721a8b3b2..ef31c0f4ac 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -12,13 +12,69 @@ concurrency: jobs: test-packages: - name: "Package Tests" + name: "packages / ${{ matrix.group.name }}" runs-on: oss-vm timeout-minutes: 90 env: CXX: g++-12 METEOR_HOSTED_CI: "true" + strategy: + fail-fast: false + matrix: + group: + - name: accounts + packages: >- + accounts-base accounts-password accounts-passwordless accounts-2fa + accounts-oauth accounts-ui accounts-ui-unstyled + audit-argument-checks check service-configuration + + - name: auth-social + packages: >- + oauth oauth2 oauth-encryption + accounts-facebook accounts-github accounts-google accounts-twitter + accounts-weibo accounts-meetup accounts-meteor-developer + facebook-oauth github-oauth google-oauth weibo-oauth + meetup-oauth meteor-developer-oauth + facebook-config-ui github-config-ui google-config-ui + twitter-config-ui weibo-config-ui + + - name: database + packages: >- + mongo minimongo allow-deny diff-sequence mongo-id disable-oplog + geojson-utils id-map ordered-dict binary-heap + mongo-livedata npm-mongo npm-mongo-legacy + + - name: ddp-realtime + packages: >- + ddp ddp-client ddp-common ddp-server ddp-rate-limiter + rate-limit inter-process-messaging autoupdate reload + reload-safetybelt routepolicy + + - name: build + packages: >- + babel-compiler babel-runtime ecmascript ecmascript-runtime + ecmascript-runtime-client ecmascript-runtime-server + caching-compiler typescript minifier-css minifier-js + standard-minifier-css static-html-tools es5-shim + constraint-solver package-version-parser + modules modules-runtime modules-runtime-hot + + - name: webapp + packages: >- + webapp webapp-hashing boilerplate-generator + boilerplate-generator-tests hot-code-push server-render + browser-policy browser-policy-common browser-policy-content + browser-policy-framing shell-server force-ssl force-ssl-common + dev-error-overlay react-fast-refresh + + - name: core + packages: >- + meteor core-runtime base64 ejson random tracker reactive-var + reactive-dict callback-hook retry url promise session + dynamic-import localstorage fetch roles facts-base facts-ui + logic-solver insecure autopublish test-helpers rspack + steps: - name: Fix workspace permissions # Self-hosted runners may leave files owned by root from previous runs. @@ -57,93 +113,5 @@ jobs: sudo apt-get install -y g++-12 fi - - name: Run all package groups in parallel - run: | - # Each group runs in a subshell: output is piped through sed to prefix - # every line with "[group]" for real-time readability. The subshell - # exits with run.sh's exit code via ${PIPESTATUS[0]}, so `wait` below - # correctly reflects test failures rather than sed's exit code. - ( - LISTENING_PORT=4101 ./packages/test-in-console/run.sh \ - accounts-base accounts-password accounts-passwordless accounts-2fa \ - accounts-oauth accounts-ui accounts-ui-unstyled \ - audit-argument-checks check service-configuration \ - 2>&1 | sed 's/^/[accounts] /' - exit "${PIPESTATUS[0]}" - ) & pid_accounts=$! - - ( - LISTENING_PORT=4102 ./packages/test-in-console/run.sh \ - oauth oauth2 oauth-encryption \ - accounts-facebook accounts-github accounts-google accounts-twitter \ - accounts-weibo accounts-meetup accounts-meteor-developer \ - facebook-oauth github-oauth google-oauth weibo-oauth \ - meetup-oauth meteor-developer-oauth \ - facebook-config-ui github-config-ui google-config-ui \ - twitter-config-ui weibo-config-ui \ - 2>&1 | sed 's/^/[auth-social] /' - exit "${PIPESTATUS[0]}" - ) & pid_auth_social=$! - - ( - LISTENING_PORT=4103 ./packages/test-in-console/run.sh \ - mongo minimongo allow-deny diff-sequence mongo-id disable-oplog \ - geojson-utils id-map ordered-dict binary-heap \ - mongo-livedata npm-mongo npm-mongo-legacy \ - 2>&1 | sed 's/^/[database] /' - exit "${PIPESTATUS[0]}" - ) & pid_database=$! - - ( - LISTENING_PORT=4104 ./packages/test-in-console/run.sh \ - ddp ddp-client ddp-common ddp-server ddp-rate-limiter \ - rate-limit inter-process-messaging autoupdate reload \ - reload-safetybelt routepolicy \ - 2>&1 | sed 's/^/[ddp-realtime] /' - exit "${PIPESTATUS[0]}" - ) & pid_ddp_realtime=$! - - ( - LISTENING_PORT=4105 ./packages/test-in-console/run.sh \ - babel-compiler babel-runtime ecmascript ecmascript-runtime \ - ecmascript-runtime-client ecmascript-runtime-server \ - caching-compiler typescript minifier-css minifier-js \ - standard-minifier-css static-html-tools es5-shim \ - constraint-solver package-version-parser \ - modules modules-runtime modules-runtime-hot \ - 2>&1 | sed 's/^/[build] /' - exit "${PIPESTATUS[0]}" - ) & pid_build=$! - - ( - LISTENING_PORT=4106 ./packages/test-in-console/run.sh \ - webapp webapp-hashing boilerplate-generator \ - boilerplate-generator-tests hot-code-push server-render \ - browser-policy browser-policy-common browser-policy-content \ - browser-policy-framing shell-server force-ssl force-ssl-common \ - dev-error-overlay react-fast-refresh \ - 2>&1 | sed 's/^/[webapp] /' - exit "${PIPESTATUS[0]}" - ) & pid_webapp=$! - - ( - LISTENING_PORT=4107 ./packages/test-in-console/run.sh \ - meteor core-runtime base64 ejson random tracker reactive-var \ - reactive-dict callback-hook retry url promise session \ - dynamic-import localstorage fetch roles facts-base facts-ui \ - logic-solver insecure autopublish test-helpers rspack \ - 2>&1 | sed 's/^/[core] /' - exit "${PIPESTATUS[0]}" - ) & pid_core=$! - - # Wait for all groups and collect failures. - failed=0 - for group in accounts auth-social database ddp-realtime build webapp core; do - var="pid_${group//-/_}" - wait "${!var}" && status=0 || status=$? - if [ $status -ne 0 ]; then - echo "::error::Group '$group' failed (exit $status)" - failed=1 - fi - done - exit $failed + - name: Run tests (${{ matrix.group.name }}) + run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 9dd30a3c5c..1f554fb410 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -18,8 +18,7 @@ fi export PATH=$METEOR_HOME:$PATH -export LISTENING_PORT=${LISTENING_PORT:-4096} -export URL="http://127.0.0.1:${LISTENING_PORT}/" +export URL='http://127.0.0.1:4096/' export METEOR_PACKAGE_DIRS='packages/deprecated' # --- Hosted CI mode --- @@ -40,12 +39,21 @@ if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" fi -exec 3< <(./meteor test-packages --driver-package test-in-console -p $LISTENING_PORT --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") +exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT sed '/test-in-console listening$/q' <&3 +# Wait until the HTTP server is actually accepting connections before launching +# Puppeteer. 'test-in-console listening' is emitted by the test driver before +# the HTTP port is fully bound, so a bare goto() would time out on slow starts. +echo "Waiting for test server at $URL..." +until curl --silent --output /dev/null --fail "$URL"; do + sleep 1 +done +echo "Test server is ready." + node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? From 16d941d4a977f1f2c01ff30f0ad946e747d25a07 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 1 Apr 2026 23:07:31 -0300 Subject: [PATCH 12/38] DEV: kill sleep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEV: 🚀 DEV: last parallelism test --- packages/test-in-console/run.sh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 1f554fb410..57af741fb9 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -45,15 +45,6 @@ trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT sed '/test-in-console listening$/q' <&3 -# Wait until the HTTP server is actually accepting connections before launching -# Puppeteer. 'test-in-console listening' is emitted by the test driver before -# the HTTP port is fully bound, so a bare goto() would time out on slow starts. -echo "Waiting for test server at $URL..." -until curl --silent --output /dev/null --fail "$URL"; do - sleep 1 -done -echo "Test server is ready." - node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? From 868624c76d1acdee2e32f1db67687702b87b5de1 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Thu, 2 Apr 2026 19:28:31 -0300 Subject: [PATCH 13/38] testing parallelism --- .github/docker/test-packages.Dockerfile | 85 +++++++++++++++++++++++++ .github/workflows/test-packages.yml | 55 +++++++++++----- 2 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 .github/docker/test-packages.Dockerfile diff --git a/.github/docker/test-packages.Dockerfile b/.github/docker/test-packages.Dockerfile new file mode 100644 index 0000000000..fe2c0da17c --- /dev/null +++ b/.github/docker/test-packages.Dockerfile @@ -0,0 +1,85 @@ +FROM ubuntu:22.04 + +LABEL org.opencontainers.image.description="Meteor package test runner (test-in-console)" + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC \ + LANG=C.UTF-8 + +# ── System build tools + Chrome system libraries ─────────────────────────────── +# +# â€ĸ g++-12 — compile native Node.js add-ons (e.g. fibers) +# â€ĸ build-essential — make, gcc, etc. required by node-gyp +# â€ĸ The font/lib entries are Chrome's runtime dependencies. +# Ubuntu 22.04 ships Chromium as a snap, which cannot run inside a container, +# so we install Google Chrome Stable from the official Google apt repository +# in the next layer instead. +# +RUN apt-get update && apt-get install -y --no-install-recommends \ + # toolchain + g++-12 \ + build-essential \ + python3 \ + make \ + curl \ + git \ + ca-certificates \ + gnupg \ + # Chrome runtime library dependencies + fonts-liberation \ + libasound2 \ + libatk-bridge2.0-0 \ + libatk1.0-0 \ + libcups2 \ + libdrm2 \ + libgbm1 \ + libnspr4 \ + libnss3 \ + libxcomposite1 \ + libxdamage1 \ + libxfixes3 \ + libxkbcommon0 \ + libxrandr2 \ + libxss1 \ + libxtst6 \ + && rm -rf /var/lib/apt/lists/* + +# ── Google Chrome Stable ─────────────────────────────────────────────────────── +# +# Pulled from Google's official apt repository so the version is always +# recent enough to be compatible with the pinned puppeteer release, and +# because the standard Ubuntu 22.04 chromium-browser package is a snap +# wrapper that does not work inside Docker containers. +# +RUN curl -fsSL https://dl.google.com/linux/linux_signing_key.pub \ + | gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg \ + && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] \ + http://dl.google.com/linux/chrome/deb/ stable main" \ + > /etc/apt/sources.list.d/google-chrome.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends google-chrome-stable \ + && rm -rf /var/lib/apt/lists/* + +# ── Node.js 20.x ────────────────────────────────────────────────────────────── +# +# Required to run `npm install -g puppeteer` at image build time and to +# bootstrap Meteor's dev_bundle on first run. +# +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && rm -rf /var/lib/apt/lists/* + +# ── Puppeteer (global) ───────────────────────────────────────────────────────── +# +# â€ĸ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD — avoid pulling a second Chrome binary; +# we use the Google Chrome installation from the previous layer instead. +# â€ĸ PUPPETEER_EXECUTABLE_PATH — point the puppeteer library at that binary. +# â€ĸ NODE_PATH — make `require('puppeteer')` resolve to the +# global install from anywhere inside the mounted workspace, so run.sh skips +# the slow `./meteor npm install -g puppeteer` step. +# +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ + PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \ + NODE_PATH=/usr/local/lib/node_modules + +RUN npm install -g puppeteer@23.6.0 diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index ef31c0f4ac..8eab2f8789 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -86,11 +86,17 @@ jobs: with: submodules: recursive - - name: Expose globally-installed puppeteer to Node.js - # puppeteer@23.6.0 is pre-installed on oss-vm via `npm install -g`. - # Setting NODE_PATH lets `require('puppeteer')` resolve it directly, - # so run.sh skips the slow `./meteor npm install -g puppeteer` step. - run: echo "NODE_PATH=$(npm root -g)" >> "$GITHUB_ENV" + - name: Build test container image + # Build once per runner; subsequent matrix jobs on the same machine hit + # the Docker layer cache and finish in seconds. + # The build context is limited to .github/docker/ — no source code is + # sent to the daemon, keeping the build fast. + run: | + docker build \ + --file .github/docker/test-packages.Dockerfile \ + --tag meteor-test-packages:local \ + --cache-from meteor-test-packages:local \ + .github/docker - name: Restore caches uses: actions/cache@v4 @@ -104,14 +110,33 @@ jobs: restore-keys: | ${{ runner.os }}-meteor- - - name: Install system dependencies - # g++-12 is needed to build native Node.js add-ons (e.g. fibers). - # All Chromium dependencies are already satisfied on oss-vm. - run: | - if ! dpkg -s g++-12 >/dev/null 2>&1; then - sudo apt-get update - sudo apt-get install -y g++-12 - fi - - name: Run tests (${{ matrix.group.name }}) - run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} + # Each matrix job runs inside its own Docker container so that + # concurrent suites on the same oss-vm get isolated network namespaces. + # This prevents port 4096 and Meteor's embedded MongoDB from colliding + # with sibling jobs running on the same host. + # + # Key flags: + # --rm — discard the container after the run + # --shm-size=2gb — Chrome requires more shared memory than Docker's 64 MB default + # --user — run as the runner uid/gid so volume-mounted files + # (workspace, npm cache) retain their original ownership + # -v WORKSPACE — the checked-out source and all restored caches + # (.meteor, dev_bundle, .babel-cache) live here + # -v HOME/.npm — reuse the npm cache restored by actions/cache + # --env HOME — tell Node/npm where the cache directory is inside the container + run: | + docker run --rm \ + --shm-size=2gb \ + --user "$(id -u):$(id -g)" \ + --env HOME="$HOME" \ + --env CXX=g++-12 \ + --env METEOR_HOSTED_CI=true \ + --env NODE_PATH=/usr/local/lib/node_modules \ + --env PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ + --env PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \ + -v "$GITHUB_WORKSPACE:$GITHUB_WORKSPACE" \ + -v "$HOME/.npm:$HOME/.npm" \ + -w "$GITHUB_WORKSPACE" \ + meteor-test-packages:local \ + ./packages/test-in-console/run.sh ${{ matrix.group.packages }} From 8ff666fb8171c59e3af2fab07fdf0b50956bdf90 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 11:00:05 -0300 Subject: [PATCH 14/38] testing something --- .github/workflows/test-packages.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 8eab2f8789..ebb545b449 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -124,12 +124,18 @@ jobs: # -v WORKSPACE — the checked-out source and all restored caches # (.meteor, dev_bundle, .babel-cache) live here # -v HOME/.npm — reuse the npm cache restored by actions/cache - # --env HOME — tell Node/npm where the cache directory is inside the container + # HOME=/tmp — Chrome's crashpad writes to $HOME/.local; /tmp is + # always world-writable regardless of runner uid, + # avoiding "Permission denied" when the runner uid does + # not own /home/ubuntu inside the Ubuntu base image. + # npm_config_cache — pin npm's cache to the volume-mounted host path so + # it is still reused even though HOME is now /tmp. run: | docker run --rm \ --shm-size=2gb \ --user "$(id -u):$(id -g)" \ - --env HOME="$HOME" \ + --env HOME=/tmp \ + --env npm_config_cache="$HOME/.npm" \ --env CXX=g++-12 \ --env METEOR_HOSTED_CI=true \ --env NODE_PATH=/usr/local/lib/node_modules \ From aadd560e2e9616ec9f759e808027b6c0db782796 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 11:25:28 -0300 Subject: [PATCH 15/38] err testing something agai --- .github/workflows/test-packages.yml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index ebb545b449..9c06febc4a 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -120,29 +120,28 @@ jobs: # --rm — discard the container after the run # --shm-size=2gb — Chrome requires more shared memory than Docker's 64 MB default # --user — run as the runner uid/gid so volume-mounted files - # (workspace, npm cache) retain their original ownership + # (workspace, home dir) retain their original ownership # -v WORKSPACE — the checked-out source and all restored caches # (.meteor, dev_bundle, .babel-cache) live here - # -v HOME/.npm — reuse the npm cache restored by actions/cache - # HOME=/tmp — Chrome's crashpad writes to $HOME/.local; /tmp is - # always world-writable regardless of runner uid, - # avoiding "Permission denied" when the runner uid does - # not own /home/ubuntu inside the Ubuntu base image. - # npm_config_cache — pin npm's cache to the volume-mounted host path so - # it is still reused even though HOME is now /tmp. + # -v HOME:HOME — bind-mount the runner's real home directory at the + # same path inside the container. This lets Chrome's + # crashpad write to $HOME/.local (the runner uid owns + # the host path, so the write succeeds), and lets + # Meteor read/write $HOME/.meteor without hitting + # first-run interactive prompts in a bare /tmp. + # The npm cache ($HOME/.npm) is included automatically. run: | docker run --rm \ --shm-size=2gb \ --user "$(id -u):$(id -g)" \ - --env HOME=/tmp \ - --env npm_config_cache="$HOME/.npm" \ + --env HOME="$HOME" \ --env CXX=g++-12 \ --env METEOR_HOSTED_CI=true \ --env NODE_PATH=/usr/local/lib/node_modules \ --env PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ --env PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \ -v "$GITHUB_WORKSPACE:$GITHUB_WORKSPACE" \ - -v "$HOME/.npm:$HOME/.npm" \ + -v "$HOME:$HOME" \ -w "$GITHUB_WORKSPACE" \ meteor-test-packages:local \ ./packages/test-in-console/run.sh ${{ matrix.group.packages }} From 4afb4a69dc7156ad02fc72b6f0c5ad05c94146ec Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 11:42:44 -0300 Subject: [PATCH 16/38] revert and testing something 2 --- .github/docker/test-packages.Dockerfile | 85 ------------------------- .github/workflows/test-packages.yml | 60 +++++------------ 2 files changed, 15 insertions(+), 130 deletions(-) delete mode 100644 .github/docker/test-packages.Dockerfile diff --git a/.github/docker/test-packages.Dockerfile b/.github/docker/test-packages.Dockerfile deleted file mode 100644 index fe2c0da17c..0000000000 --- a/.github/docker/test-packages.Dockerfile +++ /dev/null @@ -1,85 +0,0 @@ -FROM ubuntu:22.04 - -LABEL org.opencontainers.image.description="Meteor package test runner (test-in-console)" - -ARG DEBIAN_FRONTEND=noninteractive -ENV TZ=UTC \ - LANG=C.UTF-8 - -# ── System build tools + Chrome system libraries ─────────────────────────────── -# -# â€ĸ g++-12 — compile native Node.js add-ons (e.g. fibers) -# â€ĸ build-essential — make, gcc, etc. required by node-gyp -# â€ĸ The font/lib entries are Chrome's runtime dependencies. -# Ubuntu 22.04 ships Chromium as a snap, which cannot run inside a container, -# so we install Google Chrome Stable from the official Google apt repository -# in the next layer instead. -# -RUN apt-get update && apt-get install -y --no-install-recommends \ - # toolchain - g++-12 \ - build-essential \ - python3 \ - make \ - curl \ - git \ - ca-certificates \ - gnupg \ - # Chrome runtime library dependencies - fonts-liberation \ - libasound2 \ - libatk-bridge2.0-0 \ - libatk1.0-0 \ - libcups2 \ - libdrm2 \ - libgbm1 \ - libnspr4 \ - libnss3 \ - libxcomposite1 \ - libxdamage1 \ - libxfixes3 \ - libxkbcommon0 \ - libxrandr2 \ - libxss1 \ - libxtst6 \ - && rm -rf /var/lib/apt/lists/* - -# ── Google Chrome Stable ─────────────────────────────────────────────────────── -# -# Pulled from Google's official apt repository so the version is always -# recent enough to be compatible with the pinned puppeteer release, and -# because the standard Ubuntu 22.04 chromium-browser package is a snap -# wrapper that does not work inside Docker containers. -# -RUN curl -fsSL https://dl.google.com/linux/linux_signing_key.pub \ - | gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg \ - && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] \ - http://dl.google.com/linux/chrome/deb/ stable main" \ - > /etc/apt/sources.list.d/google-chrome.list \ - && apt-get update \ - && apt-get install -y --no-install-recommends google-chrome-stable \ - && rm -rf /var/lib/apt/lists/* - -# ── Node.js 20.x ────────────────────────────────────────────────────────────── -# -# Required to run `npm install -g puppeteer` at image build time and to -# bootstrap Meteor's dev_bundle on first run. -# -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* - -# ── Puppeteer (global) ───────────────────────────────────────────────────────── -# -# â€ĸ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD — avoid pulling a second Chrome binary; -# we use the Google Chrome installation from the previous layer instead. -# â€ĸ PUPPETEER_EXECUTABLE_PATH — point the puppeteer library at that binary. -# â€ĸ NODE_PATH — make `require('puppeteer')` resolve to the -# global install from anywhere inside the mounted workspace, so run.sh skips -# the slow `./meteor npm install -g puppeteer` step. -# -ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ - PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \ - NODE_PATH=/usr/local/lib/node_modules - -RUN npm install -g puppeteer@23.6.0 diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 9c06febc4a..ef31c0f4ac 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -86,17 +86,11 @@ jobs: with: submodules: recursive - - name: Build test container image - # Build once per runner; subsequent matrix jobs on the same machine hit - # the Docker layer cache and finish in seconds. - # The build context is limited to .github/docker/ — no source code is - # sent to the daemon, keeping the build fast. - run: | - docker build \ - --file .github/docker/test-packages.Dockerfile \ - --tag meteor-test-packages:local \ - --cache-from meteor-test-packages:local \ - .github/docker + - name: Expose globally-installed puppeteer to Node.js + # puppeteer@23.6.0 is pre-installed on oss-vm via `npm install -g`. + # Setting NODE_PATH lets `require('puppeteer')` resolve it directly, + # so run.sh skips the slow `./meteor npm install -g puppeteer` step. + run: echo "NODE_PATH=$(npm root -g)" >> "$GITHUB_ENV" - name: Restore caches uses: actions/cache@v4 @@ -110,38 +104,14 @@ jobs: restore-keys: | ${{ runner.os }}-meteor- - - name: Run tests (${{ matrix.group.name }}) - # Each matrix job runs inside its own Docker container so that - # concurrent suites on the same oss-vm get isolated network namespaces. - # This prevents port 4096 and Meteor's embedded MongoDB from colliding - # with sibling jobs running on the same host. - # - # Key flags: - # --rm — discard the container after the run - # --shm-size=2gb — Chrome requires more shared memory than Docker's 64 MB default - # --user — run as the runner uid/gid so volume-mounted files - # (workspace, home dir) retain their original ownership - # -v WORKSPACE — the checked-out source and all restored caches - # (.meteor, dev_bundle, .babel-cache) live here - # -v HOME:HOME — bind-mount the runner's real home directory at the - # same path inside the container. This lets Chrome's - # crashpad write to $HOME/.local (the runner uid owns - # the host path, so the write succeeds), and lets - # Meteor read/write $HOME/.meteor without hitting - # first-run interactive prompts in a bare /tmp. - # The npm cache ($HOME/.npm) is included automatically. + - name: Install system dependencies + # g++-12 is needed to build native Node.js add-ons (e.g. fibers). + # All Chromium dependencies are already satisfied on oss-vm. run: | - docker run --rm \ - --shm-size=2gb \ - --user "$(id -u):$(id -g)" \ - --env HOME="$HOME" \ - --env CXX=g++-12 \ - --env METEOR_HOSTED_CI=true \ - --env NODE_PATH=/usr/local/lib/node_modules \ - --env PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ - --env PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \ - -v "$GITHUB_WORKSPACE:$GITHUB_WORKSPACE" \ - -v "$HOME:$HOME" \ - -w "$GITHUB_WORKSPACE" \ - meteor-test-packages:local \ - ./packages/test-in-console/run.sh ${{ matrix.group.packages }} + if ! dpkg -s g++-12 >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y g++-12 + fi + + - name: Run tests (${{ matrix.group.name }}) + run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} From ae307fd269397ca3a02083efebe01206864b319c Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 11:53:15 -0300 Subject: [PATCH 17/38] one more try --- packages/test-in-console/run.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 57af741fb9..1ee3b34b6d 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -18,7 +18,14 @@ fi export PATH=$METEOR_HOME:$PATH -export URL='http://127.0.0.1:4096/' +# Pick a port that is unique per concurrent runner on the same host so that +# multiple matrix jobs running simultaneously on one machine do not collide. +# We derive an offset from the runner name (e.g. "actions-runner20" → 20) and +# add it to the base port 4096. When no runner number is present (local runs) +# the offset is 0, so the default 4096 is used unchanged. +_RUNNER_NUM=$(echo "${RUNNER_NAME:-}" | tr -dc '0-9' | sed 's/^0*//') +_PORT=$(( 4096 + ${_RUNNER_NUM:-0} )) +export URL="http://127.0.0.1:$_PORT/" export METEOR_PACKAGE_DIRS='packages/deprecated' # --- Hosted CI mode --- @@ -39,7 +46,7 @@ if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" fi -exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") +exec 3< <(./meteor test-packages --driver-package test-in-console -p "$_PORT" --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT From 4b208916a51e85bd47f6d0be550d13b06b0a22a9 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 11:59:40 -0300 Subject: [PATCH 18/38] Debugging --- packages/test-in-console/run.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 1ee3b34b6d..0ac104de51 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -46,12 +46,28 @@ if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" fi -exec 3< <(./meteor test-packages --driver-package test-in-console -p "$_PORT" --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@") +# Merge stderr into stdout so all Meteor output is captured on fd3. +# This ensures crash messages (which go to stderr) are visible when sed +# exits on EOF, rather than being silently discarded. +exec 3< <(./meteor test-packages --driver-package test-in-console -p "$_PORT" --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@" 2>&1) EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT +# Print everything Meteor outputs until it signals it is ready. +# If Meteor crashes before printing "test-in-console listening", sed exits on +# EOF. We then check whether the process is still alive and fail loudly so +# the CI log shows the actual crash output rather than a misleading +# ERR_CONNECTION_REFUSED from Puppeteer. sed '/test-in-console listening$/q' <&3 +if ! kill -0 "$EXEC_PID" 2>/dev/null; then + echo "" >&2 + echo "error: meteor test-packages exited before the server started listening on port $_PORT." >&2 + echo "Check the output above for the actual crash reason." >&2 + pkill -TERM -P $EXEC_PID 2>/dev/null || true + exit 1 +fi + node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? From 596c2ce9457adc7dcc0b526a10f226dc0a25644b Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 12:19:26 -0300 Subject: [PATCH 19/38] testing something 2 --- .github/workflows/test-packages.yml | 25 ++--- .github/workflows/warn-testless-packages.yml | 98 ++++++++++++++++++++ 2 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/warn-testless-packages.yml diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index ef31c0f4ac..1f01bcbda2 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -26,8 +26,8 @@ jobs: - name: accounts packages: >- accounts-base accounts-password accounts-passwordless accounts-2fa - accounts-oauth accounts-ui accounts-ui-unstyled - audit-argument-checks check service-configuration + accounts-oauth accounts-ui-unstyled + audit-argument-checks check - name: auth-social packages: >- @@ -36,19 +36,17 @@ jobs: accounts-weibo accounts-meetup accounts-meteor-developer facebook-oauth github-oauth google-oauth weibo-oauth meetup-oauth meteor-developer-oauth - facebook-config-ui github-config-ui google-config-ui - twitter-config-ui weibo-config-ui - name: database packages: >- - mongo minimongo allow-deny diff-sequence mongo-id disable-oplog + mongo minimongo allow-deny diff-sequence mongo-id geojson-utils id-map ordered-dict binary-heap - mongo-livedata npm-mongo npm-mongo-legacy + npm-mongo npm-mongo-legacy - name: ddp-realtime packages: >- - ddp ddp-client ddp-common ddp-server ddp-rate-limiter - rate-limit inter-process-messaging autoupdate reload + ddp-client ddp-common ddp-server ddp-rate-limiter + rate-limit inter-process-messaging reload reload-safetybelt routepolicy - name: build @@ -62,18 +60,15 @@ jobs: - name: webapp packages: >- - webapp webapp-hashing boilerplate-generator - boilerplate-generator-tests hot-code-push server-render - browser-policy browser-policy-common browser-policy-content - browser-policy-framing shell-server force-ssl force-ssl-common - dev-error-overlay react-fast-refresh + webapp webapp-hashing boilerplate-generator-tests server-render + browser-policy force-ssl-common - name: core packages: >- meteor core-runtime base64 ejson random tracker reactive-var reactive-dict callback-hook retry url promise session - dynamic-import localstorage fetch roles facts-base facts-ui - logic-solver insecure autopublish test-helpers rspack + dynamic-import localstorage fetch roles facts-base + logic-solver test-helpers rspack steps: - name: Fix workspace permissions diff --git a/.github/workflows/warn-testless-packages.yml b/.github/workflows/warn-testless-packages.yml new file mode 100644 index 0000000000..e67219fa81 --- /dev/null +++ b/.github/workflows/warn-testless-packages.yml @@ -0,0 +1,98 @@ +name: Warn — testless package changes + +on: + pull_request: + paths: + - "packages/**" + +jobs: + check: + name: Check for testless package changes + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + # Need the full base commit to diff against, not just the tip. + fetch-depth: 0 + + - name: Find changed testless packages + id: check + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: | + # Collect the unique package directory names touched by this PR. + changed=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" \ + | grep '^packages/' \ + | cut -d/ -f2 \ + | sort -u) + + testless="" + for pkg in $changed; do + pkg_js="packages/$pkg/package.js" + # A package "has tests" when its package.js contains Package.onTest. + if [ -f "$pkg_js" ] && ! grep -q 'Package\.onTest' "$pkg_js"; then + testless="$testless $pkg" + fi + done + + # Trim leading space and export for the next step. + testless="${testless# }" + echo "testless=$testless" >> "$GITHUB_OUTPUT" + + if [ -n "$testless" ]; then + echo "The following changed packages have no tests: $testless" + fi + + - name: Post or update PR comment + if: steps.check.outputs.testless != '' + uses: actions/github-script@v7 + with: + script: | + const MARKER = ''; + const pkgs = `${{ steps.check.outputs.testless }}`.trim().split(/\s+/); + const list = pkgs.map(p => `- \`${p}\``).join('\n'); + + const body = [ + MARKER, + '## âš ī¸ Changes to packages without tests', + '', + 'The following package(s) modified in this PR have no `Package.onTest`', + 'block and are **excluded from the automated test suite**:', + '', + list, + '', + 'Please either:', + '- Add a `Package.onTest` block to each package and include it in the', + ' [`test-packages` workflow](.github/workflows/test-packages.yml), or', + '- Make sure the change is covered by tests in another package that', + ' depends on this one and is already in the test matrix.', + ].join('\n'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const existing = comments.find(c => c.body.includes(MARKER)); + + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + } From 9734ff382db64413a81c83e0359d8f85c432282e Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 12:29:19 -0300 Subject: [PATCH 20/38] removed more that do not have tests --- .github/workflows/test-packages.yml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 1f01bcbda2..d7c1906609 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -26,22 +26,18 @@ jobs: - name: accounts packages: >- accounts-base accounts-password accounts-passwordless accounts-2fa - accounts-oauth accounts-ui-unstyled - audit-argument-checks check + accounts-oauth accounts-ui-unstyled check - name: auth-social packages: >- oauth oauth2 oauth-encryption - accounts-facebook accounts-github accounts-google accounts-twitter - accounts-weibo accounts-meetup accounts-meteor-developer facebook-oauth github-oauth google-oauth weibo-oauth meetup-oauth meteor-developer-oauth - name: database packages: >- - mongo minimongo allow-deny diff-sequence mongo-id - geojson-utils id-map ordered-dict binary-heap - npm-mongo npm-mongo-legacy + mongo minimongo allow-deny diff-sequence + geojson-utils binary-heap - name: ddp-realtime packages: >- @@ -51,12 +47,11 @@ jobs: - name: build packages: >- - babel-compiler babel-runtime ecmascript ecmascript-runtime - ecmascript-runtime-client ecmascript-runtime-server - caching-compiler typescript minifier-css minifier-js - standard-minifier-css static-html-tools es5-shim + ecmascript ecmascript-runtime + typescript minifier-css minifier-js + static-html-tools constraint-solver package-version-parser - modules modules-runtime modules-runtime-hot + modules-runtime modules-runtime-hot - name: webapp packages: >- @@ -65,9 +60,9 @@ jobs: - name: core packages: >- - meteor core-runtime base64 ejson random tracker reactive-var - reactive-dict callback-hook retry url promise session - dynamic-import localstorage fetch roles facts-base + meteor base64 ejson random tracker + reactive-dict callback-hook url promise session + localstorage fetch roles facts-base logic-solver test-helpers rspack steps: From 37bb678d001a57569e298887a7031bd617c38b9a Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 12:34:02 -0300 Subject: [PATCH 21/38] trying another port strategy --- packages/test-in-console/run.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 0ac104de51..f7933f3aa7 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -21,10 +21,13 @@ export PATH=$METEOR_HOME:$PATH # Pick a port that is unique per concurrent runner on the same host so that # multiple matrix jobs running simultaneously on one machine do not collide. # We derive an offset from the runner name (e.g. "actions-runner20" → 20) and -# add it to the base port 4096. When no runner number is present (local runs) +# multiply by 2 so that each runner gets two consecutive ports: one for the +# Meteor HTTP server and one for the MongoDB instance that Meteor spawns on +# PORT+1. Without this gap, runner N's Mongo (PORT+1) would collide with +# runner N+1's HTTP port. When no runner number is present (local runs) # the offset is 0, so the default 4096 is used unchanged. _RUNNER_NUM=$(echo "${RUNNER_NAME:-}" | tr -dc '0-9' | sed 's/^0*//') -_PORT=$(( 4096 + ${_RUNNER_NUM:-0} )) +_PORT=$(( 4096 + ${_RUNNER_NUM:-0} * 2 )) export URL="http://127.0.0.1:$_PORT/" export METEOR_PACKAGE_DIRS='packages/deprecated' From 8446f98b3d59cd1b038f3dfb91bfedf1def2fbd8 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Fri, 3 Apr 2026 12:50:00 -0300 Subject: [PATCH 22/38] doing what ai has told me --- packages/test-in-console/run.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index f7933f3aa7..9586cdfa80 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -63,10 +63,18 @@ trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT # ERR_CONNECTION_REFUSED from Puppeteer. sed '/test-in-console listening$/q' <&3 +# Drain remaining Meteor output so the process is never blocked on a full pipe. +# Without this, Meteor's write() calls stall once the kernel pipe buffer fills +# (e.g. from npm-dep update lines), which freezes its HTTP server and causes +# Puppeteer's navigation to time out. +cat <&3 >/dev/null & +_DRAIN_PID=$! + if ! kill -0 "$EXEC_PID" 2>/dev/null; then echo "" >&2 echo "error: meteor test-packages exited before the server started listening on port $_PORT." >&2 echo "Check the output above for the actual crash reason." >&2 + kill $_DRAIN_PID 2>/dev/null || true pkill -TERM -P $EXEC_PID 2>/dev/null || true exit 1 fi @@ -75,5 +83,6 @@ node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js STATUS=$? +kill $_DRAIN_PID 2>/dev/null || true pkill -TERM -P $EXEC_PID exit $STATUS From f728e359f1389b5c406768ed80e9779704c979a8 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Mon, 6 Apr 2026 10:25:35 -0300 Subject: [PATCH 23/38] testing something 2 --- packages/test-in-console/puppeteer_runner.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/test-in-console/puppeteer_runner.js b/packages/test-in-console/puppeteer_runner.js index a2e0578489..8349e20b5f 100644 --- a/packages/test-in-console/puppeteer_runner.js +++ b/packages/test-in-console/puppeteer_runner.js @@ -58,10 +58,14 @@ async function runNextUrl(browser) { } // Use domcontentloaded: Meteor apps connect via DDP after DOM parse and never - // fire the default 'load' event in the traditional sense. Increase timeout to - // 120 s to handle slow first-run builds on CI / underpowered machines. + // fire the default 'load' event in the traditional sense. + // Set timeout to 0 (disabled) because Meteor's HTTP server accepts the + // connection immediately after printing "test-in-console listening", but only + // sends the response once the client bundle finishes compiling — which can + // take several minutes on a cold cache for heavier package groups. The + // overall job timeout (90 min) acts as the safety net. await page.goto(process.env.URL, { - timeout: 120000, + timeout: 0, waitUntil: "domcontentloaded", }); From b433a00e488777bf3d7aa786fd5751e2c0a3b38d Mon Sep 17 00:00:00 2001 From: italo jose Date: Mon, 6 Apr 2026 17:51:56 -0300 Subject: [PATCH 24/38] feat: integrate type coverage reporting and CI workflow with updated TypeScript configuration --- .github/workflows/type-coverage.yml | 14 + .gitignore | 3 + package-lock.json | 402 +++++++++++++++++++++++++++- package.json | 12 +- tsconfig.json | 17 +- 5 files changed, 441 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/type-coverage.yml diff --git a/.github/workflows/type-coverage.yml b/.github/workflows/type-coverage.yml new file mode 100644 index 0000000000..0005c0206e --- /dev/null +++ b/.github/workflows/type-coverage.yml @@ -0,0 +1,14 @@ +name: Type Coverage +on: + - pull_request +jobs: + type-coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22.x + - run: npm install + - name: Check TypeScript type coverage (100%) + run: npm run ts-coverage:ci diff --git a/.gitignore b/.gitignore index 4742e13056..6ec7d2270d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ packages/**/.npm # doc files should not be committed packages/**/*.docs.js +# coverage +coverage-ts/ + #cursor .cursorignore .cursorrules diff --git a/package-lock.json b/package-lock.json index a94c9cf4c0..1c389dc831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,13 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "prettier": "^2.8.8", - "typescript": "^5.4.5" + "react": "^18.3.1", + "react-dom": "^18.3.1", + "semantic-ui-css": "^2.5.0", + "semantic-ui-react": "^2.1.5", + "type-coverage": "^2.29.7", + "typescript": "^5.4.5", + "typescript-coverage-report": "^1.1.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -532,6 +538,17 @@ "node": ">=6.9.0" } }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -650,6 +667,35 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fluentui/react-component-event-listener": { + "version": "0.63.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz", + "integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/@fluentui/react-component-ref": { + "version": "0.63.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz", + "integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "react-is": "^16.6.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -803,6 +849,32 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@semantic-ui-react/event-stack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz", + "integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "exenv": "^1.2.2", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1711,6 +1783,32 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1731,6 +1829,16 @@ "dev": true, "license": "MIT" }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1919,6 +2027,13 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -2703,6 +2818,13 @@ "node": ">=0.10.0" } }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3287,6 +3409,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -3525,6 +3657,13 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jquery": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-4.0.0.tgz", + "integrity": "sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg==", + "dev": true, + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3602,6 +3741,13 @@ "node": ">=4.0" } }, + "node_modules/keyboard-key": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz", + "integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ==", + "dev": true, + "license": "MIT" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3642,6 +3788,20 @@ "node": ">= 0.8.0" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3732,6 +3892,16 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "dev": true, + "license": "MIT", + "bin": { + "ncp": "bin/ncp" + } + }, "node_modules/node-releases": { "version": "2.0.36", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", @@ -3739,6 +3909,16 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4065,12 +4245,62 @@ } ] }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "dev": true, + "license": "MIT" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -4230,6 +4460,52 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semantic-ui-css": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/semantic-ui-css/-/semantic-ui-css-2.5.0.tgz", + "integrity": "sha512-jIWn3WXXE2uSaWCcB+gVJVRG3masIKtTMNEP2X8Aw909H2rHpXGneYOxzO3hT8TpyvB5/dEEo9mBFCitGwoj1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "jquery": "x.*" + } + }, + "node_modules/semantic-ui-react": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.5.tgz", + "integrity": "sha512-nIqmmUNpFHfovEb+RI2w3E2/maZQutd8UIWyRjf1SLse+XF51hI559xbz/sLN3O6RpLjr/echLOOXwKCirPy3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@fluentui/react-component-event-listener": "~0.63.0", + "@fluentui/react-component-ref": "~0.63.0", + "@popperjs/core": "^2.6.0", + "@semantic-ui-react/event-stack": "^3.1.3", + "clsx": "^1.1.1", + "keyboard-key": "^1.1.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "prop-types": "^15.7.2", + "react-is": "^16.8.6 || ^17.0.0 || ^18.0.0", + "react-popper": "^2.3.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4271,6 +4547,13 @@ "node": ">= 0.4" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4319,6 +4602,21 @@ "node": ">=8" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -4516,6 +4814,77 @@ "node": ">= 0.8.0" } }, + "node_modules/type-coverage": { + "version": "2.29.7", + "resolved": "https://registry.npmjs.org/type-coverage/-/type-coverage-2.29.7.tgz", + "integrity": "sha512-E67Chw7SxFe++uotisxt/xzB1UxxvLztzzQqVyUZ/jKujsejVqvoO5vn25oMvqJydqYrASBVBCQCy082E2qQYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "minimist": "1", + "type-coverage-core": "^2.29.7" + }, + "bin": { + "type-coverage": "bin/type-coverage" + } + }, + "node_modules/type-coverage-core": { + "version": "2.29.7", + "resolved": "https://registry.npmjs.org/type-coverage-core/-/type-coverage-core-2.29.7.tgz", + "integrity": "sha512-bt+bnXekw3p5NnqiZpNupOOxfUKGw2Z/YJedfGHkxpeyGLK7DZ59a6Wds8eq1oKjJc5Wulp2xL207z8FjFO14Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3", + "minimatch": "6 || 7 || 8 || 9 || 10", + "normalize-path": "3", + "tslib": "1 || 2", + "tsutils": "3" + }, + "peerDependencies": { + "typescript": "2 || 3 || 4 || 5" + } + }, + "node_modules/type-coverage-core/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/type-coverage-core/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/type-coverage-core/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", @@ -4602,6 +4971,27 @@ "node": ">=14.17" } }, + "node_modules/typescript-coverage-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/typescript-coverage-report/-/typescript-coverage-report-1.1.1.tgz", + "integrity": "sha512-tQt/wzYaQ7f2oPOVjU54DACxKXbpRx6soUWgsQZP7i+GRm5s/52YTpFj7ARiIT2oRWf3aH3ba/xf3KfURE9ukQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "cli-table3": "^0.6.1", + "commander": "^5.0.0", + "ncp": "^2.0.0", + "rimraf": "^3.0.2", + "type-coverage-core": "^2.23.0" + }, + "bin": { + "typescript-coverage-report": "dist/bin/typescript-coverage-report.js" + }, + "peerDependencies": { + "typescript": "2 || 3 || 4 || 5" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -4663,6 +5053,16 @@ "punycode": "^2.1.0" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 6c4f6cc640..c52fefc637 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,13 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "prettier": "^2.8.8", - "typescript": "^5.4.5" + "react": "^18.3.1", + "react-dom": "^18.3.1", + "semantic-ui-css": "^2.5.0", + "semantic-ui-react": "^2.1.5", + "type-coverage": "^2.29.7", + "typescript": "^5.4.5", + "typescript-coverage-report": "^1.1.1" }, "scripts": { "install:unit": "cd tools/unit-tests && npm install", @@ -40,7 +46,9 @@ "test:idle-bot": "node --test .github/scripts/__tests__/inactive-issues.test.js", "install:e2e": "cd tools/modern-tests && npm install && npx playwright install --with-deps chromium chromium-headless-shell", "test:e2e": "cd tools/modern-tests && npm test -- ", - "checkout:pr": "node scripts/checkout-pr.js" + "checkout:pr": "node scripts/checkout-pr.js", + "ts-coverage": "typescript-coverage-report", + "ts-coverage:ci": "type-coverage --at-least 90" }, "jshintConfig": { "esversion": 11 diff --git a/tsconfig.json b/tsconfig.json index 62b3d0ced7..ad53110358 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,18 +7,27 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist", - "rootDir": "./src", + "noEmit": true, + "allowJs": true, + "checkJs": false, + "moduleResolution": "node", "typeRoots": [ "./node_modules/@types", "./types" ] }, "include": [ - "src/**/*.ts", - "src/**/*.d.ts", + "packages/**/*.ts", + "tools/**/*.ts", "types/**/*.d.ts" ], "exclude": [ - "node_modules" + "node_modules", + "**/node_modules/**", + "**/.npm/**", + "tools/static-assets/skel*/**", + "tools/static-assets/scaffolds*/**", + "tools/tests/**", + "tools/modern-tests/**" ] } \ No newline at end of file From 197398d16f86b4c836094fd5e4221fbf5807ee25 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Tue, 7 Apr 2026 09:18:12 -0300 Subject: [PATCH 25/38] Revert "DEV: testing parallel" This reverts commit c4b83550d203c3aaff2b33f8601eee8915fdb848. --- .github/workflows/test-packages.yml | 60 ++---------- .github/workflows/warn-testless-packages.yml | 98 -------------------- packages/test-in-console/puppeteer_runner.js | 10 +- packages/test-in-console/run.sh | 64 ++----------- 4 files changed, 23 insertions(+), 209 deletions(-) delete mode 100644 .github/workflows/warn-testless-packages.yml diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index d7c1906609..88305db15f 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -12,58 +12,10 @@ concurrency: jobs: test-packages: - name: "packages / ${{ matrix.group.name }}" runs-on: oss-vm timeout-minutes: 90 env: CXX: g++-12 - METEOR_HOSTED_CI: "true" - - strategy: - fail-fast: false - matrix: - group: - - name: accounts - packages: >- - accounts-base accounts-password accounts-passwordless accounts-2fa - accounts-oauth accounts-ui-unstyled check - - - name: auth-social - packages: >- - oauth oauth2 oauth-encryption - facebook-oauth github-oauth google-oauth weibo-oauth - meetup-oauth meteor-developer-oauth - - - name: database - packages: >- - mongo minimongo allow-deny diff-sequence - geojson-utils binary-heap - - - name: ddp-realtime - packages: >- - ddp-client ddp-common ddp-server ddp-rate-limiter - rate-limit inter-process-messaging reload - reload-safetybelt routepolicy - - - name: build - packages: >- - ecmascript ecmascript-runtime - typescript minifier-css minifier-js - static-html-tools - constraint-solver package-version-parser - modules-runtime modules-runtime-hot - - - name: webapp - packages: >- - webapp webapp-hashing boilerplate-generator-tests server-render - browser-policy force-ssl-common - - - name: core - packages: >- - meteor base64 ejson random tracker - reactive-dict callback-hook url promise session - localstorage fetch roles facts-base - logic-solver test-helpers rspack steps: - name: Fix workspace permissions @@ -103,5 +55,13 @@ jobs: sudo apt-get install -y g++-12 fi - - name: Run tests (${{ matrix.group.name }}) - run: ./packages/test-in-console/run.sh ${{ matrix.group.packages }} + - name: Run test-in-console suite + run: | + export TEST_PACKAGES_EXCLUDE="stylus" + export METEOR_MODERN="true" + export NODE_ENV="CI" + export CXX="g++-12" + export phantom="false" + export TIMEOUT_SCALE_FACTOR="20" + export METEOR_HEADLESS="true" + ./packages/test-in-console/run.sh diff --git a/.github/workflows/warn-testless-packages.yml b/.github/workflows/warn-testless-packages.yml deleted file mode 100644 index e67219fa81..0000000000 --- a/.github/workflows/warn-testless-packages.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Warn — testless package changes - -on: - pull_request: - paths: - - "packages/**" - -jobs: - check: - name: Check for testless package changes - runs-on: ubuntu-latest - permissions: - pull-requests: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - # Need the full base commit to diff against, not just the tip. - fetch-depth: 0 - - - name: Find changed testless packages - id: check - env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: | - # Collect the unique package directory names touched by this PR. - changed=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" \ - | grep '^packages/' \ - | cut -d/ -f2 \ - | sort -u) - - testless="" - for pkg in $changed; do - pkg_js="packages/$pkg/package.js" - # A package "has tests" when its package.js contains Package.onTest. - if [ -f "$pkg_js" ] && ! grep -q 'Package\.onTest' "$pkg_js"; then - testless="$testless $pkg" - fi - done - - # Trim leading space and export for the next step. - testless="${testless# }" - echo "testless=$testless" >> "$GITHUB_OUTPUT" - - if [ -n "$testless" ]; then - echo "The following changed packages have no tests: $testless" - fi - - - name: Post or update PR comment - if: steps.check.outputs.testless != '' - uses: actions/github-script@v7 - with: - script: | - const MARKER = ''; - const pkgs = `${{ steps.check.outputs.testless }}`.trim().split(/\s+/); - const list = pkgs.map(p => `- \`${p}\``).join('\n'); - - const body = [ - MARKER, - '## âš ī¸ Changes to packages without tests', - '', - 'The following package(s) modified in this PR have no `Package.onTest`', - 'block and are **excluded from the automated test suite**:', - '', - list, - '', - 'Please either:', - '- Add a `Package.onTest` block to each package and include it in the', - ' [`test-packages` workflow](.github/workflows/test-packages.yml), or', - '- Make sure the change is covered by tests in another package that', - ' depends on this one and is already in the test matrix.', - ].join('\n'); - - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - }); - - const existing = comments.find(c => c.body.includes(MARKER)); - - if (existing) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id, - body, - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body, - }); - } diff --git a/packages/test-in-console/puppeteer_runner.js b/packages/test-in-console/puppeteer_runner.js index 8349e20b5f..a2e0578489 100644 --- a/packages/test-in-console/puppeteer_runner.js +++ b/packages/test-in-console/puppeteer_runner.js @@ -58,14 +58,10 @@ async function runNextUrl(browser) { } // Use domcontentloaded: Meteor apps connect via DDP after DOM parse and never - // fire the default 'load' event in the traditional sense. - // Set timeout to 0 (disabled) because Meteor's HTTP server accepts the - // connection immediately after printing "test-in-console listening", but only - // sends the response once the client bundle finishes compiling — which can - // take several minutes on a cold cache for heavier package groups. The - // overall job timeout (90 min) acts as the safety net. + // fire the default 'load' event in the traditional sense. Increase timeout to + // 120 s to handle slow first-run builds on CI / underpowered machines. await page.goto(process.env.URL, { - timeout: 0, + timeout: 120000, waitUntil: "domcontentloaded", }); diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 9586cdfa80..06d1fed2a3 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -18,71 +18,27 @@ fi export PATH=$METEOR_HOME:$PATH -# Pick a port that is unique per concurrent runner on the same host so that -# multiple matrix jobs running simultaneously on one machine do not collide. -# We derive an offset from the runner name (e.g. "actions-runner20" → 20) and -# multiply by 2 so that each runner gets two consecutive ports: one for the -# Meteor HTTP server and one for the MongoDB instance that Meteor spawns on -# PORT+1. Without this gap, runner N's Mongo (PORT+1) would collide with -# runner N+1's HTTP port. When no runner number is present (local runs) -# the offset is 0, so the default 4096 is used unchanged. -_RUNNER_NUM=$(echo "${RUNNER_NAME:-}" | tr -dc '0-9' | sed 's/^0*//') -_PORT=$(( 4096 + ${_RUNNER_NUM:-0} * 2 )) -export URL="http://127.0.0.1:$_PORT/" +export URL='http://127.0.0.1:4096/' export METEOR_PACKAGE_DIRS='packages/deprecated' -# --- Hosted CI mode --- -# Set METEOR_HOSTED_CI=true to automatically apply CI environment settings and -# exclude Blaze packages (maintained separately at github.com/meteor/blaze) -# and all packages under packages/deprecated/. -if [ "${METEOR_HOSTED_CI:-}" = "true" ]; then - echo "running in hosted CI mode: excluding Blaze and deprecated packages from test run" - export METEOR_MODERN="${METEOR_MODERN:-true}" - export NODE_ENV="${NODE_ENV:-CI}" - export METEOR_HEADLESS="${METEOR_HEADLESS:-true}" - - # Blaze packages — maintained at github.com/meteor/blaze - _BLAZE="blaze,blaze-hot,blaze-html-templates,blaze-tools,caching-html-compiler,html-tools,htmljs,observe-sequence,spacebars,spacebars-compiler,spacebars-tests,templating,templating-compiler,templating-runtime,templating-tools,ui" - # Packages in packages/deprecated/ — kept for backwards compatibility only - _DEPRECATED="amplify,appcache,backbone,code-prettify,context,d3,deps,facebook,facts,fastclick,github,google,handlebars,http,jquery-history,jquery-layout,jquery-waypoints,jsparse,jshint,livedata,markdown,meetup,meteor-developer,meteor-platform,meyerweb-reset,npm-bcrypt,preserve-inputs,showdown,spiderable,srp,standard-app-packages,startup,stylus,twitter,underscore,underscore-tests,weibo" - - export TEST_PACKAGES_EXCLUDE="${TEST_PACKAGES_EXCLUDE:+${TEST_PACKAGES_EXCLUDE},}${_BLAZE},${_DEPRECATED}" -fi - -# Merge stderr into stdout so all Meteor output is captured on fd3. -# This ensures crash messages (which go to stderr) are visible when sed -# exits on EOF, rather than being silently discarded. -exec 3< <(./meteor test-packages --driver-package test-in-console -p "$_PORT" --exclude ${TEST_PACKAGES_EXCLUDE:-''} "$@" 2>&1) +exec 3< <(./meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''} $1) EXEC_PID=$! trap "pkill -TERM -P $EXEC_PID; exit 1" SIGINT -# Print everything Meteor outputs until it signals it is ready. -# If Meteor crashes before printing "test-in-console listening", sed exits on -# EOF. We then check whether the process is still alive and fail loudly so -# the CI log shows the actual crash output rather than a misleading -# ERR_CONNECTION_REFUSED from Puppeteer. sed '/test-in-console listening$/q' <&3 -# Drain remaining Meteor output so the process is never blocked on a full pipe. -# Without this, Meteor's write() calls stall once the kernel pipe buffer fills -# (e.g. from npm-dep update lines), which freezes its HTTP server and causes -# Puppeteer's navigation to time out. -cat <&3 >/dev/null & -_DRAIN_PID=$! - -if ! kill -0 "$EXEC_PID" 2>/dev/null; then - echo "" >&2 - echo "error: meteor test-packages exited before the server started listening on port $_PORT." >&2 - echo "Check the output above for the actual crash reason." >&2 - kill $_DRAIN_PID 2>/dev/null || true - pkill -TERM -P $EXEC_PID 2>/dev/null || true - exit 1 -fi +# Wait until the HTTP server is actually accepting connections before launching +# Puppeteer. 'test-in-console listening' is emitted by the test driver before +# the HTTP port is fully bound, so a bare goto() would time out on slow starts. +echo "Waiting for test server at $URL..." +until curl --silent --output /dev/null --fail "$URL"; do + sleep 1 +done +echo "Test server is ready." node --trace-warnings "$METEOR_HOME/packages/test-in-console/puppeteer_runner.js" STATUS=$? -kill $_DRAIN_PID 2>/dev/null || true pkill -TERM -P $EXEC_PID exit $STATUS From 7595c3558619b2639047c779cd8f48f0abc72086 Mon Sep 17 00:00:00 2001 From: italo jose Date: Tue, 7 Apr 2026 09:45:22 -0300 Subject: [PATCH 26/38] chore: remove unused dependencies from package.json --- package.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/package.json b/package.json index c52fefc637..027ed37cee 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,6 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "prettier": "^2.8.8", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "semantic-ui-css": "^2.5.0", - "semantic-ui-react": "^2.1.5", "type-coverage": "^2.29.7", "typescript": "^5.4.5", "typescript-coverage-report": "^1.1.1" @@ -97,4 +93,4 @@ "sort-imports": "off" } } -} +} \ No newline at end of file From 444efdade7a1a7f96e6bc376a8e68c741d89a08b Mon Sep 17 00:00:00 2001 From: italo jose Date: Tue, 7 Apr 2026 12:42:59 -0300 Subject: [PATCH 27/38] chore: lower TypeScript type coverage threshold to 85% and update CI workflow to use npm ci --- .github/workflows/type-coverage.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/type-coverage.yml b/.github/workflows/type-coverage.yml index 0005c0206e..561d9b59bc 100644 --- a/.github/workflows/type-coverage.yml +++ b/.github/workflows/type-coverage.yml @@ -9,6 +9,6 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 22.x - - run: npm install - - name: Check TypeScript type coverage (100%) + - run: npm ci + - name: Check TypeScript type coverage (85%) run: npm run ts-coverage:ci diff --git a/package.json b/package.json index 027ed37cee..c0cfb142e8 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "test:e2e": "cd tools/modern-tests && npm test -- ", "checkout:pr": "node scripts/checkout-pr.js", "ts-coverage": "typescript-coverage-report", - "ts-coverage:ci": "type-coverage --at-least 90" + "ts-coverage:ci": "type-coverage --at-least 85" }, "jshintConfig": { "esversion": 11 From fb33dcac71536552f2abd75ba9e675929cad395e Mon Sep 17 00:00:00 2001 From: italo jose Date: Tue, 7 Apr 2026 12:47:42 -0300 Subject: [PATCH 28/38] chore: lower TypeScript type coverage threshold to 80% --- .github/workflows/type-coverage.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/type-coverage.yml b/.github/workflows/type-coverage.yml index 561d9b59bc..5ad809f1ec 100644 --- a/.github/workflows/type-coverage.yml +++ b/.github/workflows/type-coverage.yml @@ -10,5 +10,5 @@ jobs: with: node-version: 22.x - run: npm ci - - name: Check TypeScript type coverage (85%) + - name: Check TypeScript type coverage (80%) run: npm run ts-coverage:ci diff --git a/package.json b/package.json index c0cfb142e8..b5933ae83c 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "test:e2e": "cd tools/modern-tests && npm test -- ", "checkout:pr": "node scripts/checkout-pr.js", "ts-coverage": "typescript-coverage-report", - "ts-coverage:ci": "type-coverage --at-least 85" + "ts-coverage:ci": "type-coverage --at-least 80" }, "jshintConfig": { "esversion": 11 From 64c87755a92c031e21a4e48482e186c5c006a91e Mon Sep 17 00:00:00 2001 From: italo jose Date: Tue, 7 Apr 2026 13:17:00 -0300 Subject: [PATCH 29/38] refactor: update tsconfig include paths to exclude tools and consolidate type definitions --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index ad53110358..efc82b6271 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,8 +18,7 @@ }, "include": [ "packages/**/*.ts", - "tools/**/*.ts", - "types/**/*.d.ts" + "packages/**/*.d.ts" ], "exclude": [ "node_modules", From fd9528118652ec5f8395ee4451f45a3d5df9a052 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 8 Apr 2026 09:11:48 -0300 Subject: [PATCH 30/38] DEV: feedback comments --- .github/workflows/test-packages.yml | 9 --------- packages/test-in-console/puppeteer_runner.js | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index 88305db15f..f8ee66adf2 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -46,15 +46,6 @@ jobs: restore-keys: | ${{ runner.os }}-meteor- - - name: Install system dependencies - # g++-12 is needed to build native Node.js add-ons (e.g. fibers). - # All Chromium dependencies are already satisfied on oss-vm. - run: | - if ! dpkg -s g++-12 >/dev/null 2>&1; then - sudo apt-get update - sudo apt-get install -y g++-12 - fi - - name: Run test-in-console suite run: | export TEST_PACKAGES_EXCLUDE="stylus" diff --git a/packages/test-in-console/puppeteer_runner.js b/packages/test-in-console/puppeteer_runner.js index a2e0578489..546723de22 100644 --- a/packages/test-in-console/puppeteer_runner.js +++ b/packages/test-in-console/puppeteer_runner.js @@ -59,9 +59,9 @@ async function runNextUrl(browser) { // Use domcontentloaded: Meteor apps connect via DDP after DOM parse and never // fire the default 'load' event in the traditional sense. Increase timeout to - // 120 s to handle slow first-run builds on CI / underpowered machines. + // 90 s to handle slow first-run builds on CI / underpowered machines. await page.goto(process.env.URL, { - timeout: 120000, + timeout: 90000, waitUntil: "domcontentloaded", }); From 553e0a42932b6f25562f9260613be1ea99a55b0e Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 8 Apr 2026 09:15:25 -0300 Subject: [PATCH 31/38] DEV: make it green! --- packages/webapp/socket_file_tests.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/webapp/socket_file_tests.js b/packages/webapp/socket_file_tests.js index 19858bd65f..0bc93627bc 100644 --- a/packages/webapp/socket_file_tests.js +++ b/packages/webapp/socket_file_tests.js @@ -40,6 +40,18 @@ const getCurrentGroupName = () => { } }; +const getGroupToUse = () => { + if (isMacOS()) { + return 'staff'; + } + + if (process.env.TRAVIS) { + return 'travis'; + } + + return getCurrentGroupName() || 'root'; +}; + const removeTestSocketFile = () => { try { unlinkSync(testSocketFile); @@ -147,7 +159,7 @@ testAsyncMulti( // use UNIX_SOCKET_PATH and UNIX_SOCKET_GROUP const { httpServer, server } = prepareServer(); - const groupToUse = isMacOS() ? 'staff' : (getCurrentGroupName() || 'root'); + const groupToUse = getGroupToUse(); process.env.UNIX_SOCKET_PATH = testSocketFile; process.env.UNIX_SOCKET_GROUP = groupToUse; process.env.UNIX_SOCKET_PERMISSIONS = '777'; From 887e35977e51103fc311113c47ce733d738cde54 Mon Sep 17 00:00:00 2001 From: italo jose Date: Wed, 8 Apr 2026 14:57:26 -0300 Subject: [PATCH 32/38] chore: remove redundant workspace permission fix from test-packages workflow --- .github/workflows/test-packages.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test-packages.yml b/.github/workflows/test-packages.yml index f8ee66adf2..e64e789bfe 100644 --- a/.github/workflows/test-packages.yml +++ b/.github/workflows/test-packages.yml @@ -18,11 +18,6 @@ jobs: CXX: g++-12 steps: - - name: Fix workspace permissions - # Self-hosted runners may leave files owned by root from previous runs. - run: sudo chown -R "$(id -un):$(id -gn)" "$GITHUB_WORKSPACE" || true - working-directory: /tmp - - name: Checkout repository uses: actions/checkout@v4 with: From 3c245af2880e8ac25199b8114e549a26e9353311 Mon Sep 17 00:00:00 2001 From: Frederico Maia Date: Wed, 8 Apr 2026 16:40:08 -0300 Subject: [PATCH 33/38] fix: update date format in history.md for consistency --- v3-docs/docs/history.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v3-docs/docs/history.md b/v3-docs/docs/history.md index 2187c91936..04beed0220 100644 --- a/v3-docs/docs/history.md +++ b/v3-docs/docs/history.md @@ -12,7 +12,7 @@ This is a complete history of changes for Meteor releases. -## v3.4.0, 30-01-2026 +## v3.4.0, 2026-01-30 ### Highlights @@ -158,7 +158,7 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@copleykj](https://github.com/copleykj) ✨✨✨ -## v3.3.2, 01-09-2025 +## v3.3.2, 2025-09-01 ### Highlights @@ -227,7 +227,7 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@copleykj](https://github.com/copleykj) ✨✨✨ -## v3.3.1, 05-08-2025 +## v3.3.1, 2025-08-05 ### Highlights From 743df1d3376b67180276248c67816d10497e5875 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba Date: Wed, 8 Apr 2026 21:28:22 -0300 Subject: [PATCH 34/38] DOCS: fix generator --- v3-docs/docs/generators/changelog/versions/3.3.1.md | 4 ++-- v3-docs/docs/generators/changelog/versions/3.3.2.md | 2 +- v3-docs/docs/generators/changelog/versions/3.4.0.md | 4 ++-- .../changelog/versions/99999-generated-code-warning.md | 5 +---- v3-docs/docs/history.md | 9 +++------ 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/v3-docs/docs/generators/changelog/versions/3.3.1.md b/v3-docs/docs/generators/changelog/versions/3.3.1.md index 028fafbd92..33b0486912 100644 --- a/v3-docs/docs/generators/changelog/versions/3.3.1.md +++ b/v3-docs/docs/generators/changelog/versions/3.3.1.md @@ -1,4 +1,4 @@ -## v3.3.1, 05-08-2025 +## v3.3.1, 2025-08-05 ### Highlights @@ -113,4 +113,4 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@welkinwong](https://github.com/welkinwong) - [@Saksham-Goel1107](https://github.com/Saksham-Goel1107) -✨✨✨ +✨✨✨ diff --git a/v3-docs/docs/generators/changelog/versions/3.3.2.md b/v3-docs/docs/generators/changelog/versions/3.3.2.md index bee38d47b7..e14fbbdcc7 100644 --- a/v3-docs/docs/generators/changelog/versions/3.3.2.md +++ b/v3-docs/docs/generators/changelog/versions/3.3.2.md @@ -1,4 +1,4 @@ -## v3.3.2, 01-09-2025 +## v3.3.2, 2025-09-01 ### Highlights diff --git a/v3-docs/docs/generators/changelog/versions/3.4.0.md b/v3-docs/docs/generators/changelog/versions/3.4.0.md index 97be20f7cd..0ddfde37d2 100644 --- a/v3-docs/docs/generators/changelog/versions/3.4.0.md +++ b/v3-docs/docs/generators/changelog/versions/3.4.0.md @@ -1,4 +1,4 @@ -## v3.4.0, 30-01-2026 +## v3.4.0, 2026-01-30 ### Highlights @@ -143,4 +143,4 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@jeetburman](https://github.com/jeetburman) - [@copleykj](https://github.com/copleykj) - ✨✨✨ + ✨✨✨ diff --git a/v3-docs/docs/generators/changelog/versions/99999-generated-code-warning.md b/v3-docs/docs/generators/changelog/versions/99999-generated-code-warning.md index 4b3ea646f4..95d88dc7c4 100644 --- a/v3-docs/docs/generators/changelog/versions/99999-generated-code-warning.md +++ b/v3-docs/docs/generators/changelog/versions/99999-generated-code-warning.md @@ -8,7 +8,4 @@ This is a complete history of changes for Meteor releases. [//]: # (If you want to change something in this file) -[//]: # (go to meteor/docs/generators/changelog/docs) - - - +[//]: # (go to meteor/v3-docs/docs/generators/changelog/versions) diff --git a/v3-docs/docs/history.md b/v3-docs/docs/history.md index 04beed0220..c2177e833d 100644 --- a/v3-docs/docs/history.md +++ b/v3-docs/docs/history.md @@ -8,10 +8,7 @@ This is a complete history of changes for Meteor releases. [//]: # (If you want to change something in this file) -[//]: # (go to meteor/docs/generators/changelog/docs) - - - +[//]: # (go to meteor/v3-docs/docs/generators/changelog/versions) ## v3.4.0, 2026-01-30 ### Highlights @@ -157,7 +154,7 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@jeetburman](https://github.com/jeetburman) - [@copleykj](https://github.com/copleykj) - ✨✨✨ + ✨✨✨ ## v3.3.2, 2025-09-01 ### Highlights @@ -342,7 +339,7 @@ If you find any issues, please report them to the [Meteor issues tracker](https: - [@welkinwong](https://github.com/welkinwong) - [@Saksham-Goel1107](https://github.com/Saksham-Goel1107) -✨✨✨ +✨✨✨ ## v3.3.0, 2025-06-11 ### Highlights From e62868f52aeef8da7d79f4c707df54d31bb3b6d3 Mon Sep 17 00:00:00 2001 From: italo jose Date: Thu, 9 Apr 2026 11:24:36 -0300 Subject: [PATCH 35/38] docs: update breadcrumb comment to remove inaccurate percentage reference --- packages/non-core/bundle-visualizer/sunburst.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/non-core/bundle-visualizer/sunburst.js b/packages/non-core/bundle-visualizer/sunburst.js index baa0341066..6a4b6690fb 100644 --- a/packages/non-core/bundle-visualizer/sunburst.js +++ b/packages/non-core/bundle-visualizer/sunburst.js @@ -304,7 +304,7 @@ export class Sunburst { }); } - // Update the breadcrumb trail to show the current sequence and percentage. + // Update the breadcrumb trail to show the current sequence. updateBreadcrumbs(nodeArray) { // Data join; key function combines name and depth (= position in sequence). const trail = this.elements.trail From 818ab002d64fa429926b317fda0f4f2723ce96cb Mon Sep 17 00:00:00 2001 From: italo jose Date: Thu, 9 Apr 2026 14:29:23 -0300 Subject: [PATCH 36/38] chore: update type-coverage workflow to use oss-vm runner --- .github/workflows/type-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/type-coverage.yml b/.github/workflows/type-coverage.yml index 5ad809f1ec..e422a666ec 100644 --- a/.github/workflows/type-coverage.yml +++ b/.github/workflows/type-coverage.yml @@ -3,7 +3,7 @@ on: - pull_request jobs: type-coverage: - runs-on: ubuntu-latest + runs-on: oss-vm steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 From f8a371e6ea2f5dd7e9b21afd4e9331d928da3b9c Mon Sep 17 00:00:00 2001 From: italo jose Date: Thu, 9 Apr 2026 16:24:35 -0300 Subject: [PATCH 37/38] feat: add script to map packages to their associated pull requests and generate tracking data --- scripts/list_package_changes.sh | 129 ++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 scripts/list_package_changes.sh diff --git a/scripts/list_package_changes.sh b/scripts/list_package_changes.sh new file mode 100644 index 0000000000..12bab21341 --- /dev/null +++ b/scripts/list_package_changes.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# ============================================================================= +# list_package_changes.sh +# Lists folders changed inside /package for every open PR +# +# Usage: +# ./list_package_changes.sh [--output file.json] +# +# Examples: +# ./list_package_changes.sh +# ./list_package_changes.sh --output packages_by_pr.json +# +# Requirements: +# - gh CLI installed and authenticated (gh auth login) +# ============================================================================= + +set -euo pipefail + +OUTPUT_FILE="" +if [[ "${1:-}" == "--output" && -n "${2:-}" ]]; then + OUTPUT_FILE="$2" +fi + +# --- Check gh CLI is available and authenticated --- +if ! command -v gh &>/dev/null; then + echo "❌ gh CLI not found. Install it at https://cli.github.com/" + exit 1 +fi + +if ! gh auth status &>/dev/null 2>&1; then + echo "❌ gh CLI is not authenticated. Run: gh auth login" + exit 1 +fi + +# --- Detect owner/repo from git remote --- +REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null || echo "") +if [[ -z "$REPO" ]]; then + echo "❌ Could not detect repository. Run this script inside a git repository." + exit 1 +fi + +echo "đŸ“Ļ Repository: $REPO" +echo "âŦ‡ī¸ Fetching open PRs..." + +# --- Fetch all open PRs --- +ALL_PRS=$(gh pr list \ + --repo "$REPO" \ + --state open \ + --limit 500 \ + --json number,title,headRefName,author,url) + +TOTAL=$(echo "$ALL_PRS" | jq 'length') +echo "✅ $TOTAL open PRs found" +echo "" + +# --- Loop through each PR --- +RESULT="{}" +FOUND_ANY=false + +while IFS= read -r pr; do + PR_NUM=$(echo "$pr" | jq -r '.number') + PR_TITLE=$(echo "$pr" | jq -r '.title') + PR_BRANCH=$(echo "$pr" | jq -r '.headRefName') + PR_AUTHOR=$(echo "$pr" | jq -r '.author.login') + PR_URL=$(echo "$pr" | jq -r '.url') + + # Fetch changed files for this PR + PR_FILES=$(gh pr view "$PR_NUM" \ + --repo "$REPO" \ + --json files \ + -q '.files[].path' 2>/dev/null || echo "") + + if [[ -z "$PR_FILES" ]]; then + continue + fi + + # Filter files inside /packages and extract immediate subfolder + # e.g. packages/my-module/src/foo.ts → packages/my-module + PACKAGES=$(echo "$PR_FILES" \ + | (grep -E '^packages/' || true) \ + | awk -F'/' '{print $1"/"$2}' \ + | sort -u) + + if [[ -z "$PACKAGES" ]]; then + continue + fi + + FOUND_ANY=true + + # Print to terminal + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "PR #$PR_NUM — $PR_TITLE" + echo "👤 $PR_AUTHOR | đŸŒŋ $PR_BRANCH" + echo "🔗 $PR_URL" + echo "📁 Changed folders in /package:" + while IFS= read -r pkg; do + echo " â€ĸ $pkg" + done <<< "$PACKAGES" + echo "" + + # Accumulate JSON result — keyed by package name + PR_ENTRY=$(jq -n \ + --argjson num "$PR_NUM" \ + --arg title "$PR_TITLE" \ + --arg branch "$PR_BRANCH" \ + --arg author "$PR_AUTHOR" \ + --arg url "$PR_URL" \ + '{pr: $num, title: $title, branch: $branch, author: $author, url: $url}') + while IFS= read -r pkg; do + RESULT=$(echo "$RESULT" | jq --arg pkg "$pkg" --argjson entry "$PR_ENTRY" \ + 'if has($pkg) then .[$pkg] += [$entry] else . + {($pkg): [$entry]} end') + done <<< "$PACKAGES" + +done < <(echo "$ALL_PRS" | jq -c '.[]') + +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +if [[ "$FOUND_ANY" == false ]]; then + echo "â„šī¸ No PRs found that change files inside /packages." +else + PKG_COUNT=$(echo "$RESULT" | jq 'keys | length') + echo "📊 $PKG_COUNT package(s) touched across open PRs." +fi + +# --- Save JSON if requested --- +if [[ -n "$OUTPUT_FILE" ]]; then + echo "$RESULT" | jq '.' > "$OUTPUT_FILE" + echo "💾 Results saved to: $OUTPUT_FILE" +fi \ No newline at end of file From 788147e44447f0e8653e982c80eeabb63cbc5bd3 Mon Sep 17 00:00:00 2001 From: italo jose Date: Thu, 9 Apr 2026 16:52:58 -0300 Subject: [PATCH 38/38] chore: generate and update package change history JSON output --- scripts/list_package_changes.sh | 40 +++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/scripts/list_package_changes.sh b/scripts/list_package_changes.sh index 12bab21341..d29bb59d16 100644 --- a/scripts/list_package_changes.sh +++ b/scripts/list_package_changes.sh @@ -4,11 +4,13 @@ # Lists folders changed inside /package for every open PR # # Usage: -# ./list_package_changes.sh [--output file.json] +# ./list_package_changes.sh [--output file.json] [--exclude-author author1,author2,...] # # Examples: # ./list_package_changes.sh # ./list_package_changes.sh --output packages_by_pr.json +# ./list_package_changes.sh --exclude-author dependabot,renovate +# ./list_package_changes.sh --output packages_by_pr.json --exclude-author dependabot # # Requirements: # - gh CLI installed and authenticated (gh auth login) @@ -17,9 +19,24 @@ set -euo pipefail OUTPUT_FILE="" -if [[ "${1:-}" == "--output" && -n "${2:-}" ]]; then - OUTPUT_FILE="$2" -fi +EXCLUDE_AUTHORS="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --output) + OUTPUT_FILE="$2" + shift 2 + ;; + --exclude-author) + EXCLUDE_AUTHORS="$2" + shift 2 + ;; + *) + echo "❌ Unknown option: $1" + exit 1 + ;; + esac +done # --- Check gh CLI is available and authenticated --- if ! command -v gh &>/dev/null; then @@ -64,6 +81,21 @@ while IFS= read -r pr; do PR_AUTHOR=$(echo "$pr" | jq -r '.author.login') PR_URL=$(echo "$pr" | jq -r '.url') + # Skip excluded authors + if [[ -n "$EXCLUDE_AUTHORS" ]]; then + IFS=',' read -ra EXCLUDED <<< "$EXCLUDE_AUTHORS" + SKIP=false + for excluded in "${EXCLUDED[@]}"; do + if [[ "$PR_AUTHOR" == "$excluded" ]]; then + SKIP=true + break + fi + done + if [[ "$SKIP" == true ]]; then + continue + fi + fi + # Fetch changed files for this PR PR_FILES=$(gh pr view "$PR_NUM" \ --repo "$REPO" \