Skip to content
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

🐛 dependency_hash #48

Merged
merged 3 commits into from
Dec 20, 2023
Merged

🐛 dependency_hash #48

merged 3 commits into from
Dec 20, 2023

Conversation

juftin
Copy link
Owner

@juftin juftin commented Dec 20, 2023

Resolves #47

Changes

dependency_hash

This PR implements dependency_hash function on the plugin which is required for hatch >= 1.8.0. Before this fix the new dependency_hash behavior allows for lockfiles to be out of date without getting updated because their dependency_hash still matches.

Currently, dependency_hash calls run_pip_compile which regenerates the lockfile when needed, it then hashes super().dependency_hash() + the hash of the lockfile contents.

def dependency_hash(self) -> str:
    """
    Get the dependency hash
    """
    self.run_pip_compile()
    hatch_hash = super().dependency_hash()
    if not self.dependencies:
        return hatch_hash
    else:
        lockfile_hash = self.piptools_lock.get_hash()
        return hashlib.sha256(f"{hatch_hash}-{lockfile_hash}".encode()).hexdigest()

Testing

Integration Tests

  • New tests including the click CliRunner which allows for testing hatch CLI command with the plugin
  • More test cases for existing integration tests

Testing Environements

The project now includes a testing matrix where hatch 1.7.x, 1.8.x, and 1.9.x are all tested in addition to Python 3.8 though 3.12.

Version Pinning

After the latest tests, this plugin is found to be compatible with hatch>=1.7.0

Lock Files

Due to above mentioned version pinning all lockfiles were regenerated - I used macOS to generate these lockfiles so some linux specific dependencies will be removed.

plugin_check_command

Wrapped with safe_activation to ensure it does the right thing wherever it's used

Comment on lines 93 to 99
def dependency_hash(self) -> str:
"""
Get the dependency hash
"""
if not self.lockfile_up_to_date:
self.sync_dependencies()
return super().dependency_hash()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like calling lockfile_up_to_date / sync_dependencies here, but I'm not sure there's a way around it

Copy link
Owner Author

@juftin juftin Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/pypa/hatch/blob/d3246e957584d292319e7b93301598cdf611e902/src/hatch/cli/application.py#L107-L117

Hatch's workflow:

  1. Check current dependency_hash
  2. Compare it to stored hash
  3. If they don't match then run dependencies_in_sync / sync_dependencies
  4. Update the stored hash with hash from step 1

This is problematic because even though the dependency_hash can be the same the lockfile can be completely missing.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This eliminates the need for dependencies_in_sync / sync_dependencies to be called after dependency_hash

I've opened pypa/hatch#1168 which I think would make all of this a lot cleaner

@juftin juftin force-pushed the fix/dependency_hash branch 3 times, most recently from cea69f8 to 1f97aea Compare December 20, 2023 05:53
@juftin juftin marked this pull request as ready for review December 20, 2023 05:59
@juftin juftin self-assigned this Dec 20, 2023
@juftin juftin added the bug Something isn't working label Dec 20, 2023
@juftin juftin force-pushed the fix/dependency_hash branch 2 times, most recently from 82198d1 to 9b30506 Compare December 20, 2023 18:22
@juftin
Copy link
Owner Author

juftin commented Dec 20, 2023

Hey @oprypin could I get you to take a look at this and let me know your thoughts?

EDIT: after much commit editing I've come to a conclusion that the following is the best solution.

def dependency_hash(self) -> str:
    """
    Get the dependency hash
    """
    self.run_pip_compile()
    hatch_hash = super().dependency_hash()
    if not self.dependencies:
        return hatch_hash
    else:
        lockfile_hash = self.piptools_lock.get_hash()
        return hashlib.sha256(f"{hatch_hash}-{lockfile_hash}".encode()).hexdigest()

The lockfile is always checked whether it's out of date - the final hash takes a SHA256 of the lockfile alongside super().dependency_hash()

@juftin juftin force-pushed the fix/dependency_hash branch 2 times, most recently from 7def73b to 331b04f Compare December 20, 2023 20:46
@juftin juftin force-pushed the fix/dependency_hash branch from 331b04f to 814a325 Compare December 20, 2023 20:58
Copy link
Contributor

@oprypin oprypin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked too carefully, but all solutions applied here make sense

@juftin juftin merged commit a1cb08e into main Dec 20, 2023
9 checks passed
@juftin juftin deleted the fix/dependency_hash branch December 20, 2023 21:38
@juftin
Copy link
Owner Author

juftin commented Dec 20, 2023

🎉 This PR is included in version 1.8.3 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lockfile check not running
2 participants