SG-44731 Adopt Git LFS for vendored dependency ZIPs - #1128
julien-lang wants to merge 14 commits into
Conversation
- .tkdeploy: replace obsolete CI file exclusions (.travis.yml, appveyor.yml) with the files actually used today (.pre-commit-config.yaml, azure-pipelines.yml, build_resources.yml, codecov.yml, developer/) - azure-pipelines.yml: restrict branch trigger to master (was "*"), and temporarily pin the tk-ci-tools template ref to ticket/SG-44731-use-git-lfs for end-to-end testing before that PR merges - .gitattributes: minor formatting (blank lines, comment header for the LFS rule)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1128 +/- ##
==========================================
+ Coverage 80.09% 80.11% +0.01%
==========================================
Files 203 203
Lines 19537 19556 +19
==========================================
+ Hits 15649 15668 +19
Misses 3888 3888
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Adds _validate_lfs_content(), called at the end of _clone_then_execute_git_commands(), the shared clone path used by both the git branch and git tag descriptors (persistent downloads and transient temp-clones alike). If the checked out repo's root .gitattributes declares filter=lfs, verifies via 'git lfs ls-files --json' that tracked files were actually smudged to their real content. Raises TankGitError if: - the git-lfs binary isn't installed/on PATH, or - any tracked file is still a bare LFS pointer (not checked out). Repos that don't declare LFS tracking skip the check entirely, so there's no new dependency on git-lfs for the vast majority of existing git descriptors.
There was a problem hiding this comment.
🟡 Changes recommended
The new LFS validation parses git lfs ls-files --json using an incorrect JSON shape/field set, which will raise at runtime and block descriptor operations.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces Git LFS tracking for large vendored ZIP dependencies and adds runtime validation in the git descriptor implementation to detect unresolved LFS pointer files early, with accompanying documentation updates.
Changes:
- Track
requirements/**/*.zipvia Git LFS by updating.gitattributes. - Add an LFS validation step after git clones in
IODescriptorGitto error if LFS content isn’t resolved. - Document Git LFS requirements/constraints for git- and GitHub-release-based descriptors.
File summaries
| File | Description |
|---|---|
python/tank/descriptor/io_descriptor/git.py |
Adds _validate_lfs_content() and invokes it after clone/checkout to detect missing/unresolved Git LFS content. |
docs/descriptor.rst |
Documents Git LFS requirements for git descriptors and release-archive caveats. |
.gitattributes |
Marks requirements/**/*.zip as LFS-tracked. |
Review details
- Files reviewed: 3/8 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Add a new bare fixture repo (lfs-test-repo.git) with one file tracked via Git LFS, for use in real (non-mocked) descriptor tests. - Add skip_if_git_lfs_missing, mirroring skip_if_git_missing. - Add test_git_lfs.py covering the two behaviors _validate_lfs_content() is meant to guard: normal resolved LFS content checks out fine, and content left as unresolved pointer text (simulated via GIT_LFS_SKIP_SMUDGE=1) raises TankDescriptorError.
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved LFS validation, error-handling, compatibility, and test coverage issues remain.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (7)
docs/descriptor.rst:326
- This note is inside the
Tracking against commits in a git branchsection, so users of thegittag descriptor introduced at the earlier section will not see the new Git LFS requirement. Move the note to a shared Git-descriptor section or repeat it under the tag section so the documentation matches the base-class behavior for both descriptor types.
.. note:: If a repository uses `Git LFS <https://git-lfs.com>`_ to store some of its files
(declared via ``filter=lfs`` entries in its ``.gitattributes``), the machine
downloading the descriptor also needs ``git-lfs`` installed and initialized
(``git lfs install``). If it isn't, Toolkit will raise an error rather than
silently checking out files that still contain unresolved LFS pointer text.
python/tank/descriptor/io_descriptor/git.py:206
- The new integration tests exercise only
git_branch, while this shared hook also changesgittag downloads through therefclone path. Add a tag-based LFS case so regressions in tag checkout and validation are covered as promised by the PR.
self._validate_lfs_content(target_path)
python/tank/descriptor/io_descriptor/git.py:245
- The new error path for an unavailable git-lfs executable is not covered: the test class is skipped whenever git-lfs is missing, and the unresolved test only exercises a successful
git lfs ls-filescall withcheckout: false. Add a mocked command-failure case so regressions in this user-facing error handling are detected.
except Exception as err:
raise TankGitError(
f"{self} uses Git LFS to store some of its files, but git-lfs "
"does not appear to be installed on this machine. Install "
"it from https://git-lfs.com, run `git lfs install`, and "
"try again."
) from err
python/tank/descriptor/io_descriptor/git.py:206
- Because
_clone_then_execute_git_commandsis also used byhas_remote_access(), this new validation error is caught by that method's broadexceptand converted toFalse. For a version-less descriptor withresolve_latest=True, the factory then reports onlyCould not get latest version(or falls back to a stale cache), so the promised clear Git LFS error is lost. Propagate a dedicated LFS-validation error through the connectivity probe or handle it separately.
self._validate_lfs_content(target_path)
tests/descriptor_tests/test_git_lfs.py:32
- Because this entire class is skipped when
git-lfsis unavailable, the new error path in_validate_lfs_content()for a missing executable is never exercised in the environment that triggers it. Keep the integration tests conditional, but add a unit-level case that mocks the LFS command failure and asserts the clearTankGitErrormessage.
@skip_if_git_lfs_missing
tests/python/tank_test/tank_test_base.py:125
- The new helper docstring has two grammatical errors; please use “Tests if” and “True if” so the test utility documentation is clear.
Tests is git-lfs is available in PATH
:returns: True is git-lfs is available, False otherwise.
tests/python/tank_test/tank_test_base.py:125
- The return-value description is inverted: this helper returns
Truewhen the probe fails (git-lfs is missing) andFalseafter a successful probe. It also has grammatical errors, so the docstring should describe the actual missing-state result.
Tests is git-lfs is available in PATH
:returns: True is git-lfs is available, False otherwise.
- Files reviewed: 5/10 changed files
- Comments generated: 3
- Review effort level: Lite
carlos-villavicencio-adsk
left a comment
There was a problem hiding this comment.
LGTM. Just a couple of observations that are not blocking to move forward.
| ) | ||
| log.debug("Execution successful. stderr/stdout: '%s'" % output) | ||
|
|
||
| self._validate_lfs_content(target_path) |
There was a problem hiding this comment.
Just thinking out loud, not a real request from my side.
What if we validate the lfs content earlier to prevent doing a lot of steps that will end up meaningless when LFS is not installed? That way we can warn the user in advance.
I'm not sure if that will be possible to be honest.
There was a problem hiding this comment.
It's not possible unfortunately. We first need to clone the repo before indentifying if it's using LFS.
Problem
Adopts Git LFS for large vendored/binary files in
tk-coreto reduce repo/clone size.Changes
requirements/**/*.zip(pkgs.zipfor all supported Python versions,flow_data_sdk-beta.zip) are now tracked via Git LFS (filter=lfs diff=lfs merge=lfs -textin.gitattributes).python/tank/descriptor/io_descriptor/git.py: added_validate_lfs_content()on the sharedIODescriptorGitbase class, called after every clone in_clone_then_execute_git_commands()(covers both the branch and tag descriptors, for persistent downloads and transient temp-clones alike). If the checked out repo declaresfilter=lfsin.gitattributes, this verifies viagit lfs ls-files --jsonthat tracked files were actually resolved to real content, and raises a clear error if git-lfs isn't installed or some content is still a bare pointer, instead of silently proceeding with broken files.docs/descriptor.rst: documented the new Git LFS requirements for thegit/git_branchdescriptors (needgit-lfsinstalled, or Toolkit raises an error) and for thegithub_releasedescriptor (repo's "Include Git LFS objects in archives" GitHub setting must be enabled, since release archives otherwise contain unresolved LFS pointer files).