Wire git resolver into skill install flow#4338
Conversation
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4338 +/- ##
==========================================
+ Coverage 68.95% 69.33% +0.37%
==========================================
Files 479 479
Lines 48489 48592 +103
==========================================
+ Hits 33438 33692 +254
+ Misses 12317 12304 -13
+ Partials 2734 2596 -138 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
a1a0eea to
cad0c77
Compare
cad0c77 to
a08fde1
Compare
|
✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review. |
Large PR justification has been provided. Thank you!
a08fde1 to
e8f046f
Compare
aponcedeleonch
left a comment
There was a problem hiding this comment.
Review Comments
Potential inconsistent state on group registration failure
In Install() (skillsvc.go:221-226), if installFromGit succeeds (files written + DB record created) but registerSkillInGroup fails, the skill is installed on disk and in the DB but not added to the group. This leaves the system in an inconsistent state — the skill exists but isn't in the expected group.
Note: this is the same pattern used by the OCI install path, so it's not a regression introduced by this PR — but worth tracking as a follow-up improvement for both paths.
Missing unit test coverage
- No unit tests for
validateHostwith the SSRF bypass enabled/disabled (both branches ofisDevMode()). Since this is security-critical code, it would be good to have tests usingt.Setenv("TOOLHIVE_DEV", "true")and without it to verify the SSRF protection logic works correctly in production configuration. - No unit tests for
buildGitReferenceFromRegistryURLedge cases (e.g.,http://URL silent promotion tohttps://, already prefixed withgit://).
The gitresolver package was fully implemented but not connected to the main install path. This change integrates it so users can install skills from git repositories via direct references or registry fallback. Changes: - Add WithGitResolver option and installFromGit method to skillsvc - Detect git:// prefix in Install() before OCI reference check - Extend resolveFromRegistry to handle "git" package types alongside OCI - Add dev-mode SSRF bypass in validateHost for E2E testability - Generate mock for gitresolver.Resolver interface - Add unit tests for all git install paths (fresh, upgrade, no-op, errors) - Add E2E tests with local dumb-HTTP git server infrastructure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract helpers to bring Install, installFromGit, and resolveFromRegistry below the gocyclo threshold of 15: - installByName: plain-name install flow from Install - installFromRegistryLookup: registry resolution dispatch - applyGitInstall: store check + create/upgrade branching - writeAndPersistGitSkill: shared write + persist logic - resolveRegistryPackages: OCI/git package selection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
If registerSkillInGroup fails after a successful install, the skill was left installed on disk and in the DB but not added to the expected group. Add installAndRegister helper that wraps all five call sites with a best-effort store.Delete rollback so retries start fresh. Add unit tests for validateHost dev-mode SSRF bypass, git reference URL conversion edge cases, and group registration rollback behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e8f046f to
3106985
Compare
|
Rebased onto main and addressed all review feedback in 3106985: Inconsistent state fix — Rather than deferring, fixed it directly. Added New tests:
|
Fixes goconst lint violation where the same hash string appeared in three test functions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Integrates the existing gitresolver into the skill installation flow so skills can be installed from git:// references and from registry entries that declare a git package type, with accompanying unit/E2E coverage.
Changes:
- Add git-aware install path in
skillsvc(WithGitResolver,installFromGit, registry resolution supportinggit). - Update
gitresolverreference parsing to support dev-mode localhost/private IP usage for local E2E git servers. - Add mocks plus unit and E2E tests covering git install behavior (fresh/upgrade/no-op/errors; local dumb-HTTP server).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/api/server.go | Wires git resolver into default server/service construction. |
| pkg/skills/gitresolver/reference.go | Adds git reference detection and dev-mode behavior for local testability. |
| pkg/skills/gitresolver/resolver.go | Adds go:generate directive for mock generation. |
| pkg/skills/gitresolver/mocks/mock_resolver.go | Generated GoMock for the gitresolver.Resolver interface. |
| pkg/skills/skillsvc/skillsvc.go | Implements git install flow + registry git package fallback + shared install/group registration helper. |
| pkg/skills/skillsvc/skillsvc_test.go | Adds unit tests for git installation paths and registry git fallback. |
| test/e2e/api_skills_git_test.go | Adds E2E coverage using a local dumb-HTTP git server and temporary bare repos. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
The gitresolver package was fully implemented but had no connection to the skill install path. Users couldn't actually install skills from git repositories — the resolver sat unused.
This change integrates the git resolver so
thv skill installsupports git-based skill sources, both via explicitgit://prefix and through registry entries that specify a git package type.WithGitResolveroption andinstallFromGitmethod to skillsvc to handle git-based installsgit://prefix inInstall()before falling through to OCI reference checkresolveFromRegistryto handle"git"package types alongside OCIvalidateHostfor E2E testabilitygitresolver.ResolverinterfaceType of change
Test plan
task test)task test-e2e)Changes
pkg/api/server.gogitresolver.NewResolver()into server builderpkg/skills/gitresolver/reference.goIsGitReferencehelper, exportParseReferencepkg/skills/gitresolver/resolver.goResolverinterface declaration for mock generationpkg/skills/gitresolver/mocks/mock_resolver.goResolverinterfacepkg/skills/skillsvc/skillsvc.goWithGitResolver,installFromGit, git-aware registry resolutionpkg/skills/skillsvc/skillsvc_test.gotest/e2e/api_skills_git_test.goDoes this introduce a user-facing change?
Yes — users can now install skills from git repositories using
thv skill install git://or via registry entries with a git package type.Large PR Justification
gitresolver.Resolver(57 lines)Special notes for reviewers
validateHostfunction has a dev-mode bypass (THV_DEV_SKIP_SSRF_CHECK) to allow E2E tests to use localhost git servers. This is gated behind a build/env check and never active in production.Generated with Claude Code