mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
fix(ci): run static analysis for every tree the repo-wide audits scan (#20918)
A mobile-only diff is desktop-irrelevant, so should_run was false and every PR check skipped -- including the audits that do lint mobile/. The violation then landed on main and failed the same gate on every later PR's merge ref. Derive the trigger from the audit commands' own scan roots so the two cannot drift.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
@@ -261,6 +263,49 @@ const DESKTOP_IRRELEVANT_PREFIXES = [
|
||||
'.github/workflows/mobile-android-release.yml'
|
||||
]
|
||||
|
||||
const STATIC_ANALYSIS_AUDIT_SCRIPTS = [
|
||||
'audit:code-quality:native',
|
||||
'audit:code-quality:type-aware',
|
||||
'audit:anti-slop'
|
||||
]
|
||||
|
||||
// Positional arguments of an oxlint invocation are the trees it lints. `--config` consumes the
|
||||
// next token; every other flag here is valueless.
|
||||
function oxlintScanRoots(command) {
|
||||
const roots = []
|
||||
for (const segment of command.split('&&')) {
|
||||
const tokens = segment.trim().split(/\s+/).filter(Boolean)
|
||||
if (tokens[0] !== 'oxlint') {
|
||||
continue
|
||||
}
|
||||
for (let index = 1; index < tokens.length; index += 1) {
|
||||
if (tokens[index] === '--config') {
|
||||
index += 1
|
||||
} else if (!tokens[index].startsWith('-')) {
|
||||
roots.push(tokens[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots
|
||||
}
|
||||
|
||||
// Why derived from the commands rather than listed here: `mobile/` is desktop-irrelevant for every
|
||||
// other job, yet these audits lint it. A second, hand-maintained copy of "which trees the gate
|
||||
// reads" is what let #20702 land violations no PR check ran, so read it off the argv instead.
|
||||
function readStaticAnalysisScanRoots() {
|
||||
const manifest = join(import.meta.dirname, '../../package.json')
|
||||
const { scripts = {} } = JSON.parse(readFileSync(manifest, 'utf8'))
|
||||
return [
|
||||
...new Set(
|
||||
STATIC_ANALYSIS_AUDIT_SCRIPTS.flatMap((name) => oxlintScanRoots(scripts[name] ?? ''))
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
export const STATIC_ANALYSIS_SCAN_ROOTS = readStaticAnalysisScanRoots()
|
||||
|
||||
const STATIC_ANALYSIS_SCAN_PREFIXES = STATIC_ANALYSIS_SCAN_ROOTS.map((root) => `${root}/`)
|
||||
|
||||
export function isDocsOnlyPath(file) {
|
||||
if (DOCS_ONLY_FILES.has(file)) {
|
||||
return true
|
||||
@@ -298,10 +343,15 @@ export function classifyPrJobs(changedFiles) {
|
||||
shouldRun && (forceAll || ALWAYS_ON_CODE_JOBS.has(job) || jobDetector(job)(changedFiles))
|
||||
])
|
||||
)
|
||||
// Why outside should_run: a mobile-only diff is desktop-irrelevant and skips every job above,
|
||||
// but the repo-wide audits lint mobile/, and skipping them lands the violation on main, where
|
||||
// it then fails this same gate on every later PR's merge ref.
|
||||
jobs.static_analysis = jobs.static_analysis || changedFiles.some(isStaticAnalysisScannedPath)
|
||||
return {
|
||||
should_run: shouldRun,
|
||||
native_cache_changed: shouldRun && (emptyDiff || changedFiles.some(isNativeCacheInputPath)),
|
||||
mobile_dependencies: shouldRun && needsMobileDependencies(changedFiles),
|
||||
mobile_dependencies:
|
||||
(shouldRun || jobs.static_analysis) && needsMobileDependencies(changedFiles),
|
||||
...jobs
|
||||
}
|
||||
}
|
||||
@@ -358,6 +408,13 @@ function isDesktopIrrelevantPath(file) {
|
||||
return matchesPrefix(file, DESKTOP_IRRELEVANT_PREFIXES)
|
||||
}
|
||||
|
||||
function isStaticAnalysisScannedPath(file) {
|
||||
// Fail closed: roots we failed to parse must keep the gate, not silently drop it.
|
||||
return (
|
||||
STATIC_ANALYSIS_SCAN_PREFIXES.length === 0 || matchesPrefix(file, STATIC_ANALYSIS_SCAN_PREFIXES)
|
||||
)
|
||||
}
|
||||
|
||||
function isNativeCacheInputPath(file) {
|
||||
return NATIVE_CACHE_FILES.has(file) || matchesPrefix(file, NATIVE_CACHE_PREFIXES)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user