Conversation
Use file checksum including nested imports
|
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 42 minutes and 43 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Prepares ENSIndexer for a future “Build ID” by introducing a logical file checksum that includes nested TypeScript imports (to avoid missing changes hidden behind re-exports).
Changes:
- Added a
fileChecksum()helper that uses a TypeScript Program to gather transitive source dependencies and hash their contents. - Wired checksum computation into the Ponder indexing activation path (currently logging the per-file checksums; Build ID calculation is still TODO).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| apps/ensindexer/src/lib/indexing-engines/ponder.ts | Calls the checksum helper during activation and logs the results. |
| apps/ensindexer/src/lib/file-checksum.ts | New helper to compute a checksum for an entrypoint including nested imports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } from "ponder:registry"; | ||
|
|
||
| import { waitForEnsRainbowToBeReady } from "@/lib/ensrainbow/singleton"; | ||
| import { fileChecksum } from "@/ponder/logical-checksum"; |
There was a problem hiding this comment.
Import path looks incorrect: @/ponder/logical-checksum doesn’t exist under apps/ensindexer/src (tsconfig @/* maps to ./src/*). This will fail typecheck/build. Import fileChecksum from the module you added (e.g. @/lib/file-checksum) or add the missing src/ponder/logical-checksum.ts file.
| import { fileChecksum } from "@/ponder/logical-checksum"; | |
| import { fileChecksum } from "@/lib/file-checksum"; |
| console.log(`Logical checksum`, { | ||
| ponderConfig: ponderConfigChecksum, | ||
| ponderSchema: ponderSchemaChecksum, | ||
| ponderLogic: ponderLogicChecksum, | ||
| }); |
There was a problem hiding this comment.
This console.log will run on every startup (once per process) and will bypass the app’s structured logger. Please switch to logger (and/or gate behind a debug flag) to avoid noisy stdout in production.
| console.log(`Logical checksum`, { | |
| ponderConfig: ponderConfigChecksum, | |
| ponderSchema: ponderSchemaChecksum, | |
| ponderLogic: ponderLogicChecksum, | |
| }); | |
| if (process.env.DEBUG) { | |
| console.log(`Logical checksum`, { | |
| ponderConfig: ponderConfigChecksum, | |
| ponderSchema: ponderSchemaChecksum, | |
| ponderLogic: ponderLogicChecksum, | |
| }); | |
| } |
| // src/lib/checksum.ts | ||
|
|
There was a problem hiding this comment.
File header comment is misleading (// src/lib/checksum.ts) and doesn’t match the actual filename (file-checksum.ts). Please update or remove it to avoid confusion when navigating/searching.
| // src/lib/checksum.ts |
| import ts from "typescript"; | ||
|
|
||
| import { logger } from "@/lib/logger"; |
There was a problem hiding this comment.
fileChecksum imports typescript at runtime. In this package, typescript is currently a devDependency, so environments that install only production deps will crash when this code runs. Either move typescript to dependencies or change the implementation to avoid requiring the TypeScript compiler at runtime.
| const tsSourceFiles = new Set<string>(allTsFiles); | ||
|
|
||
| if (tsSourceFiles.size === 0) { | ||
| throw new Error(`No source files found for entry point: ${entryPoint}`); | ||
| } else { | ||
| logger.info({ | ||
| msg: "Files included in logic checksum", | ||
| entryPoint, | ||
| filesCount: tsSourceFiles.size, |
There was a problem hiding this comment.
Checksum depends on the iteration order of tsProgram.getSourceFiles(). That ordering is not part of a stable public contract, so the same project can produce different checksums across TS versions/OS, causing unnecessary Build ID churn. Sort the final file list (e.g. by normalized file path) before hashing to make the checksum deterministic.
| const tsSourceFiles = new Set<string>(allTsFiles); | |
| if (tsSourceFiles.size === 0) { | |
| throw new Error(`No source files found for entry point: ${entryPoint}`); | |
| } else { | |
| logger.info({ | |
| msg: "Files included in logic checksum", | |
| entryPoint, | |
| filesCount: tsSourceFiles.size, | |
| const tsSourceFiles = Array.from( | |
| new Map(allTsFiles.map((file) => [file.replace(/\\/g, "/"), file])).entries(), | |
| ) | |
| .sort(([normalizedFileA], [normalizedFileB]) => normalizedFileA.localeCompare(normalizedFileB)) | |
| .map(([, file]) => file); | |
| if (tsSourceFiles.length === 0) { | |
| throw new Error(`No source files found for entry point: ${entryPoint}`); | |
| } else { | |
| logger.info({ | |
| msg: "Files included in logic checksum", | |
| entryPoint, | |
| filesCount: tsSourceFiles.length, |
|
|
||
| for (const file of tsSourceFiles) { | ||
| const content = ts.sys.readFile(file); | ||
| if (content) hash.update(content); |
There was a problem hiding this comment.
If ts.sys.readFile(file) returns undefined (permissions/race/missing file), the current code silently skips that file, producing a checksum that no longer represents the full dependency set. It’s safer to throw (or at least log+fail) when any expected source file can’t be read.
| if (content) hash.update(content); | |
| if (content === undefined) { | |
| throw new Error(`Failed to read source file for checksum: ${file}`); | |
| } | |
| hash.update(content); |
| export function fileChecksum(entryPoint: string, tsConfigPath: string = "tsconfig.json"): string { | ||
| const root = process.cwd(); | ||
| const resolvedEntry = resolve(root, entryPoint); | ||
|
|
||
| logger.info({ | ||
| msg: "Computing entrypoint checksum", | ||
| entryPoint, | ||
| resolvedEntry, | ||
| }); | ||
|
|
||
| // Read tsconfig | ||
| const tsConfigFile = ts.readConfigFile(tsConfigPath, ts.sys.readFile); | ||
| if (tsConfigFile.error) { | ||
| throw new Error(`Failed to read tsconfig: ${tsConfigPath}`); | ||
| } | ||
|
|
||
| const parsedTsConfig = ts.parseJsonConfigFileContent( | ||
| tsConfigFile.config, | ||
| ts.sys, | ||
| root, | ||
| undefined, | ||
| tsConfigPath, | ||
| ); | ||
|
|
||
| const tsProgram = ts.createProgram([resolvedEntry], parsedTsConfig.options); |
There was a problem hiding this comment.
New helper has non-trivial behavior (nested import resolution + hashing) but no tests. Adding a file-checksum.test.ts with small fixture files would help lock in: (1) checksum changes when an imported file changes (even if entrypoint is only a re-export), and (2) determinism across runs.
| } from "ponder:registry"; | ||
|
|
||
| import { waitForEnsRainbowToBeReady } from "@/lib/ensrainbow/singleton"; | ||
| import { fileChecksum } from "@/ponder/logical-checksum"; |
|
|
||
| const hash = createHash("sha256"); | ||
|
|
||
| for (const file of tsSourceFiles) { |
There was a problem hiding this comment.
| for (const file of tsSourceFiles) { | |
| // Sort files to ensure deterministic hash output across different runs and machines | |
| const sortedFiles = Array.from(tsSourceFiles).sort(); | |
| for (const file of sortedFiles) { |
File checksum for Build ID is non-deterministic due to unsorted iteration over TypeScript source files returned by compiler
shrugs
left a comment
There was a problem hiding this comment.
cool! surface level read looks good to me. i don't have any expertise with ts meta stuff, so claude's probably more informed than i am
Use file checksum including nested imports
Lite PR
Tip: Review docs on the ENSNode PR process
Summary
fileChecksumhelper to create a checksum for a file in ENSIndexer app. The checksum includes all nested imports required for the file.Why
Testing
Notes for Reviewer (Optional)
Pre-Review Checklist (Blocking)