From bca2c6203f00e95416ef0ee79aca21d5b164f11b Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Wed, 28 Jan 2026 15:23:25 -0800 Subject: [PATCH] Add testing for telemetry in local dist assets --- .github/workflows/ci-dist-telemetry-scan.yaml | 36 ++++++++++++ package.json | 1 + scripts/verify-dist-no-telemetry.ts | 57 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 .github/workflows/ci-dist-telemetry-scan.yaml create mode 100644 scripts/verify-dist-no-telemetry.ts diff --git a/.github/workflows/ci-dist-telemetry-scan.yaml b/.github/workflows/ci-dist-telemetry-scan.yaml new file mode 100644 index 000000000..327cb5b6c --- /dev/null +++ b/.github/workflows/ci-dist-telemetry-scan.yaml @@ -0,0 +1,36 @@ +name: 'CI: Dist Telemetry Scan' + +on: + pull_request: + branches-ignore: [wip/*, draft/*, temp/*] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + scan: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build project + run: pnpm build + + - name: Scan dist for telemetry references + run: pnpm test:dist diff --git a/package.json b/package.json index e1b00ac12..eb67c0ecf 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "stylelint": "stylelint --cache '{apps,packages,src}/**/*.{css,vue}'", "test:browser": "pnpm exec nx e2e", "test:browser:local": "cross-env PLAYWRIGHT_LOCAL=1 pnpm test:browser", + "test:dist": "tsx scripts/verify-dist-no-telemetry.ts", "test:unit": "nx run test", "typecheck": "vue-tsc --noEmit", "typecheck:desktop": "nx run @comfyorg/desktop-ui:typecheck", diff --git a/scripts/verify-dist-no-telemetry.ts b/scripts/verify-dist-no-telemetry.ts new file mode 100644 index 000000000..ca7f70ec4 --- /dev/null +++ b/scripts/verify-dist-no-telemetry.ts @@ -0,0 +1,57 @@ +import { readFile, stat } from 'node:fs/promises' +import { extname, resolve } from 'node:path' +import { glob } from 'glob' + +type Pattern = { + label: string + regex: RegExp +} + +const distDir = resolve('dist') +const ignoredExtensions = new Set(['.map', '.svg']) +const telemetryPatterns: Pattern[] = [ + { label: 'GTM container', regex: /GTM-[A-Z0-9]+/i }, + { label: 'GTM script', regex: /gtm\.js/i }, + { label: 'Google Tag Manager', regex: /googletagmanager/i }, + { label: 'dataLayer', regex: /\bdataLayer\b/ } +] + +const distStats = await stat(distDir).catch(() => null) +if (!distStats?.isDirectory()) { + console.error('dist directory not found. Run pnpm build first.') + process.exit(1) +} + +const files = await glob('dist/**/*', { nodir: true }) +const violations: Array<{ + file: string + hits: Array<{ label: string; match: string }> +}> = [] + +for (const file of files) { + const extension = extname(file).toLowerCase() + if (ignoredExtensions.has(extension)) continue + + const content = (await readFile(file)).toString('utf8') + const hits = telemetryPatterns + .map((pattern) => { + const match = content.match(pattern.regex) + return match ? { label: pattern.label, match: match[0] } : null + }) + .filter((hit): hit is { label: string; match: string } => hit !== null) + + if (hits.length > 0) { + violations.push({ file, hits }) + } +} + +if (violations.length > 0) { + console.error('Telemetry references found in dist assets:') + for (const violation of violations) { + const formattedHits = violation.hits + .map((hit) => `${hit.label} (${hit.match})`) + .join(', ') + console.error(`- ${violation.file}: ${formattedHits}`) + } + process.exit(1) +}