diff --git a/go.mod b/go.mod index 10cdf52..2518506 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.12 toolchain go1.26.4 require ( - github.com/codefly-dev/core v0.2.74 + github.com/codefly-dev/core v0.2.78 gopkg.in/yaml.v3 v3.0.1 ) @@ -82,10 +82,12 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect + github.com/scagogogo/python-requirements-parser v0.0.0-20250717025652-6ca77234c827 // indirect github.com/sergi/go-diff v1.4.0 // indirect github.com/shirou/gopsutil/v3 v3.24.5 // indirect github.com/shoenig/go-m1cpu v0.2.1 // indirect github.com/skeema/knownhosts v1.3.2 // indirect + github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect github.com/tklauser/numcpus v0.11.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect @@ -101,6 +103,7 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.53.0 // indirect golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect + golang.org/x/mod v0.38.0 // indirect golang.org/x/net v0.56.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/term v0.44.0 // indirect diff --git a/go.sum b/go.sum index 9035092..cf14141 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJ github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/codefly-dev/core v0.2.74 h1:Y5ew338LVnttBNm/OmlHpwj56NOFPEtbX75cUhUFQT4= -github.com/codefly-dev/core v0.2.74/go.mod h1:oP2Ob8tuMJU5wkHN57cR8AcNs6WfkhqmMdTlZLqFipA= +github.com/codefly-dev/core v0.2.78 h1:v6fW62ZoS/umsjrz4oEEnSJ50nzXeeORMegB7nlXbXQ= +github.com/codefly-dev/core v0.2.78/go.mod h1:hNxTk7ZnR5AU8imfvNJcGpoULQ1uzML5M3E4/RffWU4= github.com/codefly-dev/gortk v0.2.0 h1:7bOlS5valYz2zil+fZctQNcPCYBcPj86abcw9N8h1hQ= github.com/codefly-dev/gortk v0.2.0/go.mod h1:dDWUMFgAP063OCGhTEpV7FFUj9+zTcxxO/nV80VKEwg= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -194,6 +194,8 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/scagogogo/python-requirements-parser v0.0.0-20250717025652-6ca77234c827 h1:+Fu0RVDu7WxwtkELZ9V0PjG+HdxL+ANkGKa6gp45J/g= +github.com/scagogogo/python-requirements-parser v0.0.0-20250717025652-6ca77234c827/go.mod h1:3rCK5dhjXuiTnMXVkO2n9eWZ21qWreUtptCmCT9+rNg= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= @@ -205,6 +207,8 @@ github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsB github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= +github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 h1:6C8qej6f1bStuePVkLSFxoU22XBS165D3klxlzRg8F4= +github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82/go.mod h1:xe4pgH49k4SsmkQq5OT8abwhWmnzkhpgnXeekbx2efw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= @@ -250,6 +254,8 @@ golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= +golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= +golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= diff --git a/pkg/tooling/tooling.go b/pkg/tooling/tooling.go index 79fd24f..53e9642 100644 --- a/pkg/tooling/tooling.go +++ b/pkg/tooling/tooling.go @@ -155,9 +155,16 @@ func (t *Tooling) GetProjectInfo(ctx context.Context, _ *toolingv0.GetProjectInf for _, d := range pi.Dependencies { deps = append(deps, &toolingv0.Dependency{Name: d.Name, Version: d.Version, Direct: d.Direct}) } + var sourceFiles []*toolingv0.SourceFileInfo + for _, file := range pi.GetSourceFiles() { + sourceFiles = append(sourceFiles, &toolingv0.SourceFileInfo{ + Path: file.GetPath(), Imports: append([]string(nil), file.GetImports()...), + }) + } return &toolingv0.GetProjectInfoResponse{ Module: pi.Module, Language: pi.Language, LanguageVersion: pi.LanguageVersion, - Packages: pkgs, Dependencies: deps, FileHashes: pi.FileHashes, Failure: failures.Clone(resp.GetFailure()), + Packages: pkgs, Dependencies: deps, FileHashes: pi.FileHashes, SourceFiles: sourceFiles, + Failure: failures.Clone(resp.GetFailure()), }, nil } diff --git a/pkg/tooling/tooling_test.go b/pkg/tooling/tooling_test.go index be80fca..f7bb376 100644 --- a/pkg/tooling/tooling_test.go +++ b/pkg/tooling/tooling_test.go @@ -1,8 +1,13 @@ package tooling_test import ( + "context" + "os" + "path/filepath" "testing" + codev0 "github.com/codefly-dev/core/generated/go/codefly/services/code/v0" + toolingv0 "github.com/codefly-dev/core/generated/go/codefly/services/tooling/v0" "github.com/codefly-dev/core/resources" pythoncode "github.com/codefly-dev/service-python/pkg/code" @@ -29,3 +34,39 @@ func TestToolingWiring(t *testing.T) { t.Error("Tooling.Runtime is not the Runtime passed to New") } } + +func TestProjectInfoCarriesRequirementsAndImportsAcrossCodeAndTooling(t *testing.T) { + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "requirements.in"), []byte("flask==3.1.2\n"), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, "app.py"), []byte("import flask\n"), 0o644); err != nil { + t.Fatal(err) + } + service := pythonservice.New(&resources.Agent{Kind: "codefly:service", Name: "python"}) + service.SourceLocation = dir + server := pythoncode.New(service) + + codeResponse, err := server.Execute(context.Background(), &codev0.CodeRequest{ + Operation: &codev0.CodeRequest_GetProjectInfo{GetProjectInfo: &codev0.GetProjectInfoRequest{}}, + }) + if err != nil { + t.Fatal(err) + } + project := codeResponse.GetGetProjectInfo() + if codeResponse.GetFailure() != nil || len(project.GetDependencies()) != 1 || project.GetDependencies()[0].GetName() != "flask" || + project.GetDependencies()[0].GetVersion() != "==3.1.2" || len(project.GetSourceFiles()) != 1 || + project.GetSourceFiles()[0].GetPath() != "app.py" || len(project.GetSourceFiles()[0].GetImports()) != 1 || project.GetSourceFiles()[0].GetImports()[0] != "flask" { + t.Fatalf("code project info = %+v failure=%+v", project, codeResponse.GetFailure()) + } + + toolingResponse, err := pythontooling.New(server, nil).GetProjectInfo(context.Background(), &toolingv0.GetProjectInfoRequest{}) + if err != nil { + t.Fatal(err) + } + if toolingResponse.GetFailure() != nil || len(toolingResponse.GetDependencies()) != 1 || toolingResponse.GetDependencies()[0].GetName() != "flask" || + len(toolingResponse.GetSourceFiles()) != 1 || toolingResponse.GetSourceFiles()[0].GetPath() != "app.py" || + len(toolingResponse.GetSourceFiles()[0].GetImports()) != 1 || toolingResponse.GetSourceFiles()[0].GetImports()[0] != "flask" { + t.Fatalf("tooling project info = %+v", toolingResponse) + } +}