-
Notifications
You must be signed in to change notification settings - Fork 361
[wip] Add Catalog Hash System for Dependency Tracking #3006
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Using this for consistency
🗄️ Schema Change: No Changes ✅ |
|
Size Change: 0 B Total Size: 497 kB ℹ️ View Unchanged
|
🛠️ Item Splitting: No Changes ✅ |
… dependency tracking
npm Snapshot: PublishedGood news!! We've packaged up the latest commit from this PR (60d98d2) and published it to npm. You Example: pnpm add @khanacademy/perseus@PR3006If you are working in Khan Academy's frontend, you can run the below command. ./dev/tools/bump_perseus_version.ts -t PR3006If you are working in Khan Academy's webapp, you can run the below command. ./dev/tools/bump_perseus_version.js -t PR3006 |
jeremywiebe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this Tamara! I have a few thoughts before you land this:
- we duplicate types in several places, could we centralize those so that they can't drift out of sync?
- the
utils/folder has aninternal/subfolder. Would some of these files belong in there? I think thisutils/folder should only contain executable files and any supporting files could go intointernal/. - The PR description is a bit verbose. I don't think there's value in the description outlining changed files as that is data that git will give us. It would also be nice if you could state the problem this PR solves at the outset. I think it's solving the problem of packages not being published when we bump catalog dependencies, right? Could you make that clearer in the description?
| import {updateCatalogHashes} from "./update-catalog-hashes"; | ||
|
|
||
| function printHelp() { | ||
| console.log("Usage: update-catalog-hashes [options]"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| console.log("Usage: update-catalog-hashes [options]"); | |
| console.log("Usage: update-catalog-hashes-cli.ts [options]"); |
| console.log("Examples:"); | ||
| console.log(" update-catalog-hashes"); | ||
| console.log(" update-catalog-hashes --dry-run"); | ||
| console.log(" update-catalog-hashes --verbose"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These aren't useful unless they show more complex usages of flags. As it stands, there's only two flags and they're pretty common, so examples here seems like just extra noise.
| */ | ||
| export function updateCatalogHashes(isDryRun: boolean, verbose = false): void { | ||
| // Get the set of packages that we don't publish, per the changeset config. | ||
| const {ignore = []} = loadChangesetConfig(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer we look at each package.json's private flag and/or the publishConfig. These are npm-ecosystem flags that document if the package should be published. Although the ignore config option is supported, they document that it is meant to be a temporary solution during dev.
THIS FEATURE IS DESIGNED FOR TEMPORARY USE TO ALLOW CHANGES TO BE MERGED WITHOUT PUBLISHING THEM - If you want to stop a package from being published at all, set private: true in its package.json.
| const packageJsonPaths = fastGlob.sync("**/package.json", { | ||
| absolute: true, | ||
| ignore: ["**/node_modules/**", "**/dist/**"], | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works fine, but one option that would be easier to maintain (and not require maintaining an ignore list is to use git to figure out which files to work with. Only package.json files that are checked into git should be considered... so git ls-files "package.json" "**/package.json" would find all package.json files that are tracked... meaning we'd ignore everything in any node_module/ or dist/ folder automatically.
| const unpublishedPackages = new Set<string>(ignore); | ||
| // The root package is always considered unpublished, | ||
| // but is not included in the changeset config ignore list. | ||
| unpublishedPackages.add(ROOT_PACKAGE_NAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We won't need this if we change to obey the package's private: true flag as our root package.json has this (correctly) set.
| console.log("\n🔍 Verifying catalog hashes..."); | ||
| const catalogHashResult = verifyCatalogHashes(); | ||
| if (!catalogHashResult.success) { | ||
| console.error("\n❌ Catalog hash verification failed:\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we prefix these messages with an extra newline (\n)?
|
|
||
| const ROOT_PACKAGE_NAME = "perseus"; | ||
|
|
||
| type PackageJson = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we duplicate this type in at least one other file. Maybe we should have a types.ts file in this utils/ folder that hosts these types?
| Catalog hashes ensure packages are rebuilt when their catalog dependencies (Wonder Blocks, React, etc.) are updated. These hashes are automatically updated when running `utils/sync-dependencies.ts`. If you manually add catalog dependencies to a package.json, run `pnpm update-catalog-hashes` to update the hashes. The pre-publish check will verify all hashes are current before releasing. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this is a mostly clear explanation, thanks!
Just to check my understanding, are these hashes used to trigger a publish of affected packages or just rebuilding (I'm not trying to be pedantic, but I'm unclear what we mean when we say "rebuilt")
| "sloc": "^0.2.1", | ||
| "storybook": "^9.0.4", | ||
| "storybook-multilevel-sort": "^2.0.1", | ||
| "string-hash": "^1.1.3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, we could use globalThis.crypto.subtle to do the hashing (via digest) as that's built-in to Node.
| // Assert - Empty string hashes to "5381" with string-hash | ||
| expect(result).toBe("5381"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought: We document this "magic" value in several of these tests. I wonder if it'd be clearer if we had a known string value that we use if the input string is empty. ie. what if this assertion were: expect(result).toBe("--empty--").
What are your thoughts? :)
jeremywiebe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this Tamara! I have a few thoughts before you land this:
- we duplicate types in several places, could we centralize those so that they can't drift out of sync?
- the
utils/folder has aninternal/subfolder. Would some of these files belong in there? I think thisutils/folder should only contain executable files and any supporting files could go intointernal/. - The PR description is a bit verbose. I don't think there's value in the description outlining changed files as that is data that git will give us. It would also be nice if you could state the problem this PR solves at the outset. I think it's solving the problem of packages not being published when we bump catalog dependencies, right? Could you make that clearer in the description?
Summary:
Overview
Implements a catalog hash system to track changes in pnpm catalog dependencies (Wonder Blocks, React, etc.) across Perseus packages. This ensures packages are correctly rebuilt when their catalog dependencies are updated, even if the package code itself hasn't changed.
Key Features
Non-Test Files Added
Files Modified
Dependencies
Issue: LEMS-3328
Test plan: