From ec4e03548766fd7beb284239ef3f005df239b69c Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 24 Jul 2026 14:54:47 -0700 Subject: [PATCH 01/16] fix(ci): improve changed file detection in linter script --- bin/linter.mjs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index bd9a976ca944..2e9dd5fb1aef 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -68,11 +68,23 @@ function runGit(args, options = {}) { */ function getChangedFiles() { const base = process.env.GITHUB_BASE_REF || 'main'; + + // Attempt to fetch the base branch and set origin/${base} so it doesn't compare against itself + if (process.env.GITHUB_BASE_REF) { + try { + runGit(['fetch', 'origin', base, '--depth=1']); + } catch { + // Continue if network fetch fails or remote does not exist + } + } + const refsToTry = [ + `origin/${base}...HEAD`, + `${base}...HEAD`, + `upstream/${base}...HEAD`, + `origin/${base}`, base, `upstream/${base}`, - `origin/${base}`, - 'FETCH_HEAD', 'HEAD~1', 'HEAD^', ]; From 42c173b31f642b0e0e11b1d4cabbdb7aa7dde3c8 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 24 Jul 2026 15:15:04 -0700 Subject: [PATCH 02/16] fix(ci): use explicit refspec when fetching base branch --- bin/linter.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 2e9dd5fb1aef..b36f28aa8d00 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -72,7 +72,12 @@ function getChangedFiles() { // Attempt to fetch the base branch and set origin/${base} so it doesn't compare against itself if (process.env.GITHUB_BASE_REF) { try { - runGit(['fetch', 'origin', base, '--depth=1']); + runGit([ + 'fetch', + 'origin', + `+refs/heads/${base}:refs/remotes/origin/${base}`, + '--depth=1', + ]); } catch { // Continue if network fetch fails or remote does not exist } From fa9293a32453ef2db97f12085eadf3dba032f2ff Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Mon, 27 Jul 2026 13:33:09 -0700 Subject: [PATCH 03/16] fix(linter): use namespace import for typescript ESM compatibility --- bin/linter.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index b36f28aa8d00..7d4a802a0dcb 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -17,7 +17,7 @@ import {existsSync} from 'fs'; import path from 'path'; import {promisify} from 'util'; import {ESLint} from 'eslint'; -import ts from 'typescript'; +import * as ts from 'typescript'; // --- Globals & Promisified API Wrappers --- const execFileAsync = promisify(execFile); From 50cfd226f05481a37131048cebfc319888e95499 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 14:08:07 -0700 Subject: [PATCH 04/16] fix(linter): make changed file resolution hermetic and improve base ref detection --- bin/linter.mjs | 111 +++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 7d4a802a0dcb..eb6afb9eacfe 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -63,73 +63,84 @@ function runGit(args, options = {}) { }); } +/** + * Helper to get modified/added TypeScript files against a given git ref. + * Uses merge-base when possible to compare against the common ancestor (e.g. when base and branch have both moved). + */ +function getDiffFiles(ref) { + let diffTarget = ref; + try { + const mergeBase = runGit(['merge-base', ref, 'HEAD']).trim(); + if (mergeBase) { + diffTarget = mergeBase; + } + } catch { + // If merge-base fails (e.g. shallow clone or invalid ref), fall back to using ref directly + } + + const output = runGit([ + 'diff', + '--name-only', + '--diff-filter=ACMRT', + diffTarget, + '--', + '*.ts', + ]); + return output + .split('\n') + .map(f => f.trim()) + .filter(f => f.length > 0 && existsSync(f)); +} + /** * Returns a list of changed TypeScript files comparing against target branches/references. */ function getChangedFiles() { - const base = process.env.GITHUB_BASE_REF || 'main'; + const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); - // Attempt to fetch the base branch and set origin/${base} so it doesn't compare against itself - if (process.env.GITHUB_BASE_REF) { + if (isCI) { + const baseRef = process.env.GITHUB_BASE_REF; + if (!baseRef) { + throw new Error('Running in CI but GITHUB_BASE_REF environment variable is not set.'); + } try { - runGit([ - 'fetch', - 'origin', - `+refs/heads/${base}:refs/remotes/origin/${base}`, - '--depth=1', - ]); + const files = getDiffFiles(baseRef); + console.log(`Comparing against base reference: ${baseRef}`); + return files; } catch { - // Continue if network fetch fails or remote does not exist + throw new Error(`Failed to determine changed files against GITHUB_BASE_REF '${baseRef}' in CI.`); } } - const refsToTry = [ - `origin/${base}...HEAD`, - `${base}...HEAD`, - `upstream/${base}...HEAD`, - `origin/${base}`, - base, - `upstream/${base}`, - 'HEAD~1', - 'HEAD^', - ]; + let currentBranch = ''; + try { + currentBranch = runGit(['rev-parse', '--abbrev-ref', 'HEAD']).trim(); + } catch { + // Continue with fallback refs if branch detection fails + } + + if (currentBranch === 'main') { + try { + const files = getDiffFiles('HEAD~1'); + console.log('Comparing against base reference: HEAD~1'); + return files; + } catch { + throw new Error("Failed to determine changed files against 'HEAD~1' on main branch."); + } + } + const refsToTry = ['upstream/main', 'origin/main', 'main']; for (const ref of refsToTry) { try { - const output = runGit([ - 'diff', - '--name-only', - '--diff-filter=ACMRT', - ref, - '--', - '*.ts', - ]); - return output - .split('\n') - .map(f => f.trim()) - .filter(f => f.length > 0 && existsSync(f)); + const files = getDiffFiles(ref); + console.log(`Comparing against base reference: ${ref}`); + return files; } catch { - // Continue to the next fallback ref + // Continue to next ref if this one fails/does not exist } } - // Fallback to checking uncommitted working tree changes against HEAD if all specific refs fail - try { - const output = runGit([ - 'diff', - '--name-only', - '--diff-filter=ACMRT', - 'HEAD', - '--', - '*.ts', - ]); - return output - .split('\n') - .map(f => f.trim()) - .filter(f => f.length > 0 && existsSync(f)); - } catch { - return []; - } + throw new Error(`Failed to determine changed files. Tried refs: ${refsToTry.join(', ')}`); } // --- ESLint Checker --- From 632b0531973749eda78b938c8a6cfa75a7f0c754 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 14:10:50 -0700 Subject: [PATCH 05/16] fix(linter): use default import for typescript in ESM module --- bin/linter.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index eb6afb9eacfe..75e18c6084e5 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -17,7 +17,7 @@ import {existsSync} from 'fs'; import path from 'path'; import {promisify} from 'util'; import {ESLint} from 'eslint'; -import * as ts from 'typescript'; +import ts from 'typescript'; // --- Globals & Promisified API Wrappers --- const execFileAsync = promisify(execFile); From 06c7c557d4150de192a29e3ef8b702f0a7c81b1b Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 14:16:43 -0700 Subject: [PATCH 06/16] fix(linter): check remote main refs before HEAD~1 when on main branch --- bin/linter.mjs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 75e18c6084e5..c8424a44825d 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -120,13 +120,17 @@ function getChangedFiles() { } if (currentBranch === 'main') { - try { - const files = getDiffFiles('HEAD~1'); - console.log('Comparing against base reference: HEAD~1'); - return files; - } catch { - throw new Error("Failed to determine changed files against 'HEAD~1' on main branch."); + const mainRefs = ['origin/main', 'upstream/main', 'HEAD~1']; + for (const ref of mainRefs) { + try { + const files = getDiffFiles(ref); + console.log(`Comparing against base reference: ${ref}`); + return files; + } catch { + // Continue to next ref + } } + throw new Error("Failed to determine changed files on main branch."); } const refsToTry = ['upstream/main', 'origin/main', 'main']; From 762164398bfc376725d05b607352d2ee35b6f4da Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 14:35:53 -0700 Subject: [PATCH 07/16] refactor(linter): consolidate getChangedFiles reference resolution logic --- bin/linter.mjs | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index c8424a44825d..e499490369f7 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -94,46 +94,34 @@ function getDiffFiles(ref) { /** * Returns a list of changed TypeScript files comparing against target branches/references. + * Fully hermetic (uses local git references and merge-base with no network calls). */ function getChangedFiles() { const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); + let refsToTry = []; + let isStrictCI = false; + if (isCI) { const baseRef = process.env.GITHUB_BASE_REF; if (!baseRef) { throw new Error('Running in CI but GITHUB_BASE_REF environment variable is not set.'); } + refsToTry = [baseRef]; + isStrictCI = true; + } else { + let currentBranch = ''; try { - const files = getDiffFiles(baseRef); - console.log(`Comparing against base reference: ${baseRef}`); - return files; + currentBranch = runGit(['rev-parse', '--abbrev-ref', 'HEAD']).trim(); } catch { - throw new Error(`Failed to determine changed files against GITHUB_BASE_REF '${baseRef}' in CI.`); + // Continue with fallback refs if branch detection fails } - } - let currentBranch = ''; - try { - currentBranch = runGit(['rev-parse', '--abbrev-ref', 'HEAD']).trim(); - } catch { - // Continue with fallback refs if branch detection fails + refsToTry = currentBranch === 'main' + ? ['origin/main', 'upstream/main', 'HEAD~1'] + : ['upstream/main', 'origin/main', 'main']; } - if (currentBranch === 'main') { - const mainRefs = ['origin/main', 'upstream/main', 'HEAD~1']; - for (const ref of mainRefs) { - try { - const files = getDiffFiles(ref); - console.log(`Comparing against base reference: ${ref}`); - return files; - } catch { - // Continue to next ref - } - } - throw new Error("Failed to determine changed files on main branch."); - } - - const refsToTry = ['upstream/main', 'origin/main', 'main']; for (const ref of refsToTry) { try { const files = getDiffFiles(ref); @@ -144,6 +132,10 @@ function getChangedFiles() { } } + if (isStrictCI) { + throw new Error(`Failed to determine changed files against GITHUB_BASE_REF '${refsToTry[0]}' in CI.`); + } + throw new Error(`Failed to determine changed files. Tried refs: ${refsToTry.join(', ')}`); } From 683d6279c21f806284bf8fe94202a01e078793d5 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 14:37:59 -0700 Subject: [PATCH 08/16] chore(linter): clean up comments and format branch check in linter.mjs --- bin/linter.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index e499490369f7..973973a39b69 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -94,7 +94,6 @@ function getDiffFiles(ref) { /** * Returns a list of changed TypeScript files comparing against target branches/references. - * Fully hermetic (uses local git references and merge-base with no network calls). */ function getChangedFiles() { const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); @@ -117,7 +116,7 @@ function getChangedFiles() { // Continue with fallback refs if branch detection fails } - refsToTry = currentBranch === 'main' + refsToTry = (currentBranch === 'main') ? ['origin/main', 'upstream/main', 'HEAD~1'] : ['upstream/main', 'origin/main', 'main']; } From 59154c7583d137b697e5725ad5f27dea65b9a228 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Thu, 30 Jul 2026 15:46:55 -0700 Subject: [PATCH 09/16] fix(linter): resolve origin/baseRef in CI for actions/checkout compatibility --- bin/linter.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 973973a39b69..901384f8a95c 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -106,7 +106,7 @@ function getChangedFiles() { if (!baseRef) { throw new Error('Running in CI but GITHUB_BASE_REF environment variable is not set.'); } - refsToTry = [baseRef]; + refsToTry = baseRef.startsWith('origin/') ? [baseRef] : [`origin/${baseRef}`, baseRef]; isStrictCI = true; } else { let currentBranch = ''; From 24593f8d8552a445ba4ee495ade8a0cf208e5cf2 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 11:51:21 -0700 Subject: [PATCH 10/16] feat(linter): add --strict mode changed file detection --- .github/workflows/presubmit.yaml | 2 +- bin/linter.mjs | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index dc152e2bec88..2637066ed0cd 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -41,5 +41,5 @@ jobs: with: node-version: 24 - run: npm install - - run: npm run lint + - run: node ./bin/linter.mjs --strict --git-diff-arg "origin/${{ github.base_ref }}...HEAD" name: Run monorepo linter diff --git a/bin/linter.mjs b/bin/linter.mjs index 901384f8a95c..0fd1e47a2eed 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -92,10 +92,75 @@ function getDiffFiles(ref) { .filter(f => f.length > 0 && existsSync(f)); } +/** + * Helper to get modified/added TypeScript files in strict mode given GIT_DIFF_ARG. + * Validates that `git diff --quiet ${gitDiffArg}` succeeds (exit code 0 or 1). + */ +function getStrictDiffFiles(gitDiffArg) { + const args = gitDiffArg.trim().split(/\s+/); + + try { + runGit(['diff', '--quiet', ...args]); + } catch (err) { + if (err.status !== 1) { + throw new Error( + `Strict mode error: git diff --quiet ${gitDiffArg} failed with exit code ${err.status}.\n` + + `Ensure that the git reference '${gitDiffArg}' exists locally and that you have fetched the required commits/branches.\n` + + `Details: ${String(err.stderr || err.message || '').trim()}` + ); + } + } + + const output = runGit([ + 'diff', + '--name-only', + '--diff-filter=ACMRT', + ...args, + '--', + '*.ts', + ]); + return output + .split('\n') + .map(f => f.trim()) + .filter(f => f.length > 0 && existsSync(f)); +} + +/** + * Retrieves the GIT_DIFF_ARG from CLI flags or environment variable. + */ +function getGitDiffArg() { + const cliIndex = process.argv.findIndex(arg => arg.startsWith('--git-diff-arg')); + if (cliIndex !== -1) { + const arg = process.argv[cliIndex]; + if (arg.includes('=')) { + return arg.substring(arg.indexOf('=') + 1); + } + if (process.argv[cliIndex + 1] && !process.argv[cliIndex + 1].startsWith('-')) { + return process.argv[cliIndex + 1]; + } + } + return process.env.GIT_DIFF_ARG; +} + /** * Returns a list of changed TypeScript files comparing against target branches/references. */ function getChangedFiles() { + const isStrict = process.argv.includes('--strict'); + + const gitDiffArg = getGitDiffArg(); + + if (isStrict) { + if (!gitDiffArg) { + throw new Error( + 'Strict mode is enabled (--strict), but GIT_DIFF_ARG was not provided. ' + + 'Please supply --git-diff-arg or set the GIT_DIFF_ARG environment variable.' + ); + } + console.log(`Strict mode enabled. Comparing using GIT_DIFF_ARG: ${gitDiffArg}`); + return getStrictDiffFiles(gitDiffArg); + } + const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); let refsToTry = []; From 2a00af383fc7dfb0077cafdbf930170582e3f050 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 11:51:21 -0700 Subject: [PATCH 11/16] fix(ci): fetch base branch in presubmit workflow for strict linter diff --- .github/workflows/presubmit.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index 2637066ed0cd..be6631a56c28 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -36,6 +36,8 @@ jobs: with: fetch-depth: 300 persist-credentials: false + - name: Fetch base branch for linter diff + run: git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} - name: Use Node.js 24 uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: From 01341a97a0e8104fd1bb7b22c10a4a48259608e6 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 13:47:29 -0700 Subject: [PATCH 12/16] refactor(linter): use environment variables for strict mode diff logic --- .github/workflows/presubmit.yaml | 5 +- bin/linter.mjs | 101 +++++++++++++------------------ 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index be6631a56c28..74035893d235 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -43,5 +43,8 @@ jobs: with: node-version: 24 - run: npm install - - run: node ./bin/linter.mjs --strict --git-diff-arg "origin/${{ github.base_ref }}...HEAD" + - run: node ./bin/linter.mjs name: Run monorepo linter + env: + STRICT: "true" + GIT_DIFF_ARG: "origin/${{ github.base_ref }}...HEAD" diff --git a/bin/linter.mjs b/bin/linter.mjs index 0fd1e47a2eed..55557ae0f7a3 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -26,7 +26,13 @@ const tsconfigCache = new Map(); // --- Main Runner (Entry Point) --- async function run() { try { - const changedTsFiles = getChangedFiles(); + const isStrict = Boolean(process.env.STRICT); + let changedTsFiles; + if (isStrict) { + changedTsFiles = getChangedFilesStrict(); + } else { + changedTsFiles = getChangedFiles(); + } if (changedTsFiles.length === 0) { console.log('No TypeScript files changed. Skipping checks.'); @@ -63,40 +69,18 @@ function runGit(args, options = {}) { }); } -/** - * Helper to get modified/added TypeScript files against a given git ref. - * Uses merge-base when possible to compare against the common ancestor (e.g. when base and branch have both moved). - */ -function getDiffFiles(ref) { - let diffTarget = ref; - try { - const mergeBase = runGit(['merge-base', ref, 'HEAD']).trim(); - if (mergeBase) { - diffTarget = mergeBase; - } - } catch { - // If merge-base fails (e.g. shallow clone or invalid ref), fall back to using ref directly +function getChangedFilesStrict() { + const gitDiffArg = getGitDiffArg(); + + if (!gitDiffArg) { + throw new Error( + 'Strict mode is enabled, but GIT_DIFF_ARG environment variable was not provided. ' + + 'Please set the GIT_DIFF_ARG environment variable.' + ); } - const output = runGit([ - 'diff', - '--name-only', - '--diff-filter=ACMRT', - diffTarget, - '--', - '*.ts', - ]); - return output - .split('\n') - .map(f => f.trim()) - .filter(f => f.length > 0 && existsSync(f)); -} + console.log(`Strict mode enabled. Comparing using GIT_DIFF_ARG: ${gitDiffArg}`); -/** - * Helper to get modified/added TypeScript files in strict mode given GIT_DIFF_ARG. - * Validates that `git diff --quiet ${gitDiffArg}` succeeds (exit code 0 or 1). - */ -function getStrictDiffFiles(gitDiffArg) { const args = gitDiffArg.trim().split(/\s+/); try { @@ -125,41 +109,42 @@ function getStrictDiffFiles(gitDiffArg) { .filter(f => f.length > 0 && existsSync(f)); } +function getGitDiffArg() { + return process.env.GIT_DIFF_ARG; +} + /** - * Retrieves the GIT_DIFF_ARG from CLI flags or environment variable. + * Helper to get modified/added TypeScript files against a given git ref when not in "strict mode" */ -function getGitDiffArg() { - const cliIndex = process.argv.findIndex(arg => arg.startsWith('--git-diff-arg')); - if (cliIndex !== -1) { - const arg = process.argv[cliIndex]; - if (arg.includes('=')) { - return arg.substring(arg.indexOf('=') + 1); - } - if (process.argv[cliIndex + 1] && !process.argv[cliIndex + 1].startsWith('-')) { - return process.argv[cliIndex + 1]; +function getDiffFiles(ref) { + let diffTarget = ref; + try { + const mergeBase = runGit(['merge-base', ref, 'HEAD']).trim(); + if (mergeBase) { + diffTarget = mergeBase; } + } catch { + // If merge-base fails, fall back to using ref directly } - return process.env.GIT_DIFF_ARG; + + const output = runGit([ + 'diff', + '--name-only', + '--diff-filter=ACMRT', + diffTarget, + '--', + '*.ts', + ]); + return output + .split('\n') + .map(f => f.trim()) + .filter(f => f.length > 0 && existsSync(f)); } /** - * Returns a list of changed TypeScript files comparing against target branches/references. + * Returns a list of changed TypeScript files comparing against target branches/references when not in strict mode */ function getChangedFiles() { - const isStrict = process.argv.includes('--strict'); - - const gitDiffArg = getGitDiffArg(); - - if (isStrict) { - if (!gitDiffArg) { - throw new Error( - 'Strict mode is enabled (--strict), but GIT_DIFF_ARG was not provided. ' + - 'Please supply --git-diff-arg or set the GIT_DIFF_ARG environment variable.' - ); - } - console.log(`Strict mode enabled. Comparing using GIT_DIFF_ARG: ${gitDiffArg}`); - return getStrictDiffFiles(gitDiffArg); - } const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); From dc0e3d9b258cb6fe68af644249e2a05ba6265c5c Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 13:49:06 -0700 Subject: [PATCH 13/16] style(linter): clean up unused space in getChangedFiles() --- bin/linter.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 55557ae0f7a3..0368426a6fb4 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -145,7 +145,6 @@ function getDiffFiles(ref) { * Returns a list of changed TypeScript files comparing against target branches/references when not in strict mode */ function getChangedFiles() { - const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); let refsToTry = []; From 8bbd71a7adc3fa04e88b0e4c9b148b75fe285bf6 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 13:50:38 -0700 Subject: [PATCH 14/16] refactor(linter): simplify getChangedFiles for default non-strict mode --- bin/linter.mjs | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 0368426a6fb4..8d71ae3f4de8 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -145,31 +145,17 @@ function getDiffFiles(ref) { * Returns a list of changed TypeScript files comparing against target branches/references when not in strict mode */ function getChangedFiles() { - const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITHUB_BASE_REF); - - let refsToTry = []; - let isStrictCI = false; - - if (isCI) { - const baseRef = process.env.GITHUB_BASE_REF; - if (!baseRef) { - throw new Error('Running in CI but GITHUB_BASE_REF environment variable is not set.'); - } - refsToTry = baseRef.startsWith('origin/') ? [baseRef] : [`origin/${baseRef}`, baseRef]; - isStrictCI = true; - } else { - let currentBranch = ''; - try { - currentBranch = runGit(['rev-parse', '--abbrev-ref', 'HEAD']).trim(); - } catch { - // Continue with fallback refs if branch detection fails - } - - refsToTry = (currentBranch === 'main') - ? ['origin/main', 'upstream/main', 'HEAD~1'] - : ['upstream/main', 'origin/main', 'main']; + let currentBranch = ''; + try { + currentBranch = runGit(['rev-parse', '--abbrev-ref', 'HEAD']).trim(); + } catch { + // Continue with fallback refs if branch detection fails } + const refsToTry = (currentBranch === 'main') + ? ['origin/main', 'upstream/main', 'HEAD~1'] + : ['upstream/main', 'origin/main', 'main']; + for (const ref of refsToTry) { try { const files = getDiffFiles(ref); @@ -180,10 +166,6 @@ function getChangedFiles() { } } - if (isStrictCI) { - throw new Error(`Failed to determine changed files against GITHUB_BASE_REF '${refsToTry[0]}' in CI.`); - } - throw new Error(`Failed to determine changed files. Tried refs: ${refsToTry.join(', ')}`); } From b3db78734d9caa1504973c77559921d45fca1097 Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 13:54:13 -0700 Subject: [PATCH 15/16] refactor(linter): inline process.env.GIT_DIFF_ARG directly in getChangedFilesStrict --- bin/linter.mjs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 8d71ae3f4de8..94bd541ff832 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -70,7 +70,7 @@ function runGit(args, options = {}) { } function getChangedFilesStrict() { - const gitDiffArg = getGitDiffArg(); + const gitDiffArg = process.env.GIT_DIFF_ARG; if (!gitDiffArg) { throw new Error( @@ -109,10 +109,6 @@ function getChangedFilesStrict() { .filter(f => f.length > 0 && existsSync(f)); } -function getGitDiffArg() { - return process.env.GIT_DIFF_ARG; -} - /** * Helper to get modified/added TypeScript files against a given git ref when not in "strict mode" */ From 8f0cd0faaaee8daa93687783311571e054919ace Mon Sep 17 00:00:00 2001 From: Shivanee Persaud Date: Fri, 31 Jul 2026 13:59:59 -0700 Subject: [PATCH 16/16] refactor(linter): use git diff ref...HEAD directly in getChangedFiles --- bin/linter.mjs | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/bin/linter.mjs b/bin/linter.mjs index 94bd541ff832..acf3a27be8a7 100755 --- a/bin/linter.mjs +++ b/bin/linter.mjs @@ -110,35 +110,7 @@ function getChangedFilesStrict() { } /** - * Helper to get modified/added TypeScript files against a given git ref when not in "strict mode" - */ -function getDiffFiles(ref) { - let diffTarget = ref; - try { - const mergeBase = runGit(['merge-base', ref, 'HEAD']).trim(); - if (mergeBase) { - diffTarget = mergeBase; - } - } catch { - // If merge-base fails, fall back to using ref directly - } - - const output = runGit([ - 'diff', - '--name-only', - '--diff-filter=ACMRT', - diffTarget, - '--', - '*.ts', - ]); - return output - .split('\n') - .map(f => f.trim()) - .filter(f => f.length > 0 && existsSync(f)); -} - -/** - * Returns a list of changed TypeScript files comparing against target branches/references when not in strict mode + * Returns a list of changed TypeScript files comparing against target branches/references when not in strict mode. */ function getChangedFiles() { let currentBranch = ''; @@ -154,9 +126,19 @@ function getChangedFiles() { for (const ref of refsToTry) { try { - const files = getDiffFiles(ref); + const output = runGit([ + 'diff', + '--name-only', + '--diff-filter=ACMRT', + `${ref}...HEAD`, + '--', + '*.ts', + ]); console.log(`Comparing against base reference: ${ref}`); - return files; + return output + .split('\n') + .map(f => f.trim()) + .filter(f => f.length > 0 && existsSync(f)); } catch { // Continue to next ref if this one fails/does not exist }