-
Notifications
You must be signed in to change notification settings - Fork 80
Fix dependency manager update prompts and filesystem actions #2226
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
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
1f648b3 to
6c95655
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
| // File exists - keep it at current version | ||
| msg := util.MessageWithEmojiPrefix("⏸️", fmt.Sprintf("%s kept at current version", pending.contractName)) | ||
| di.logs.stateUpdates = append(di.logs.stateUpdates, msg) |
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 is not correct. We have no guarantee that the stored file hash matches the flow.json hash at this point.
However, files are stored in a processed state, and flow.json hashes are stored in the pre-processed state, so validation becomes tricky.
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 think I got it 6c775c7
But this required changing the hashing function to consume the processed imports. Because of the fact that further dependencies are processed/handled independently anyways, and the contracts are only every used by DM in their processed representation, it seems safe to make this change.
NOTE: This will require a migration step, all devs on teams sharing projects will need to update their CLI to prevent the hash from constantly changing back and forth.
internal/cadence/linter.go
Outdated
| ) | ||
|
|
||
| var analyzers = maps.Values(cdclint.Analyzers) | ||
| // getAnalyzers returns analyzers in deterministic order (sorted by 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.
Had flakey tests due to non-determinism here, was introduced in prior PR just never saw it yet. Might as well fix it now.
turbolent
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.
Thank you for improving this!
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.
Pull request overview
This PR implements support for dependency update management through two new flags (--update and --skip-update-prompts) that control how the CLI handles outdated dependency hashes. The implementation adds validation to detect hash mismatches between local files and on-chain contracts, ensuring dependency integrity when users decline updates or skip prompts. Additionally, it includes a fix to ensure deterministic ordering of linters by sorting analyzer keys.
Key Changes
- Added mutually exclusive flags
--update(auto-accept updates) and--skip-update-prompts(auto-decline updates) with validation - Enhanced dependency installation to detect and handle hash mismatches with appropriate error messages and file system operations
- Fixed non-deterministic linter behavior by sorting analyzer keys before execution
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| internal/dependencymanager/dependencyinstaller_test.go | Adds comprehensive test coverage for dependency installation scenarios including fresh clones, outdated hashes, and flag behaviors |
| internal/dependencymanager/dependencyinstaller.go | Implements update flag logic, hash validation, file integrity checks, and deferred prompt handling with filesystem operations |
| internal/cadence/linter.go | Replaces non-deterministic map iteration with sorted key ordering for consistent linter results |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| modifiedContractCode := []byte(`access(all) contract Hello { access(all) fun sayHello(): String { return "Hello, Modified!" } }`) | ||
| newContractCode := []byte(`access(all) contract Hello { access(all) fun sayHello(): String { return "Hello, World! v2" } }`) | ||
|
|
||
| // Calculate the old hash (of the converted contract) |
Copilot
AI
Dec 19, 2025
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.
Corrected spelling of 'converted' to 'committed'.
| // Calculate the old hash (of the converted contract) | |
| // Calculate the old hash (of the committed contract) |
| // Calculate hash of converted contract (what gets written to disk) | ||
| // This is what we store in flow.json so we can verify file integrity later | ||
| // Imported contracts are still checked for consistency by traversing the dependency tree. |
Copilot
AI
Dec 19, 2025
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.
The comment on line 633 about 'Imported contracts' seems unclear in this context. Consider clarifying how imported contracts relate to the hash calculation being performed here, or remove this line if it's not directly relevant to the hash calculation logic.
| // Calculate hash of converted contract (what gets written to disk) | |
| // This is what we store in flow.json so we can verify file integrity later | |
| // Imported contracts are still checked for consistency by traversing the dependency tree. | |
| // Calculate hash of the converted contract source (the code that gets written to disk). | |
| // This hash is stored in flow.json so we can later verify that the on-disk contract | |
| // matches the version that was originally installed. Note that this hash only covers | |
| // the primary contract; any imported contracts are validated separately as part of | |
| // the dependency tree traversal logic elsewhere in the dependency manager. |
| // User chose not to update | ||
| // If file doesn't exist, we MUST fail - can't guarantee frozen deps (no way to fetch old version) | ||
| if !di.contractFileExists(pending.contractAddr, pending.contractName) { | ||
| return fmt.Errorf("dependency %s has changed on-chain but file does not exist locally. Cannot keep at current version because we have no way to fetch the old version from the blockchain. Either accept the update or manually add the contract file", pending.contractName) |
Copilot
AI
Dec 19, 2025
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 error message is quite long and could be more user-friendly. Consider breaking it into multiple lines or simplifying the explanation to improve readability.
| return fmt.Errorf("dependency %s has changed on-chain but file does not exist locally. Cannot keep at current version because we have no way to fetch the old version from the blockchain. Either accept the update or manually add the contract file", pending.contractName) | |
| return fmt.Errorf( | |
| "dependency %s has changed on-chain, but the local contract file does not exist.\n"+ | |
| "Cannot keep the current version because the previous on-chain code cannot be fetched.\n"+ | |
| "Either accept the update or manually add the contract file.", | |
| pending.contractName, | |
| ) |
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.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Closes #2224
Closes #2225
Description
Adds support for the
SkipUpdatePromptsflag, and add support for dependency filesystem changes during deferred dependency prompts. Additionally adds support for theUpdateflag.This is comparable to a
y/n/promptstate, where:Update=>ySkipUpdatePrompts=>npromptTest cases:
Additionally - hash integrity validation (such that local file matches the
flow.jsonhash) has been added to prevent these files from going out of sync.For contributor use:
masterbranchFiles changedin the Github PR explorer