Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion builder/store/database/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,22 @@ func (s *repoStoreImpl) PublicToUser(ctx context.Context, repoType types.Reposit

q.Where("repository.repository_type = ?", repoType)

// join table by repo type to filter out deleted and half-created records
switch repoType {
case types.ModelRepo:
q.Join("LEFT JOIN models ON models.repository_id = repository.id")
case types.DatasetRepo:
q.Join("LEFT JOIN datasets ON datasets.repository_id = repository.id")
case types.CodeRepo:
q.Join("LEFT JOIN codes ON codes.repository_id = repository.id")
case types.SpaceRepo:
q.Join("LEFT JOIN spaces ON spaces.repository_id = repository.id")
case types.PromptRepo:
q.Join("LEFT JOIN prompts ON prompts.repository_id = repository.id")
case types.MCPServerRepo:
q.Join("LEFT JOIN mcp_servers ON mcp_servers.repository_id = repository.id")
}

if !isAdmin {
if len(userIDs) > 0 {
q.Where("repository.private = ? or repository.user_id in (?)", false, bun.In(userIDs))
Expand Down Expand Up @@ -688,7 +704,7 @@ func (s *repoStoreImpl) PublicToUser(ctx context.Context, repoType types.Reposit
}

if len(filter.SpaceSDK) > 0 {
q.Join("LEFT JOIN spaces AS spaces ON repository.id = spaces.repository_id").Where("spaces.sdk = ?", filter.SpaceSDK)
q.Where("spaces.sdk = ?", filter.SpaceSDK)
}

if len(filter.Tags) > 0 {
Expand Down
12 changes: 12 additions & 0 deletions builder/store/database/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ func TestRepoStore_PublicToUserSimple(t *testing.T) {
})
require.Empty(t, err)
require.NotNil(t, repo)
ds := database.NewDatasetStoreWithDB(db)
_, err = ds.Create(ctx, database.Dataset{
RepositoryID: repo.ID,
})
require.Empty(t, err)

ts := database.NewTagStoreWithDB(db)
var tags []*database.Tag
Expand Down Expand Up @@ -516,6 +521,13 @@ func setupTestRepositories(ctx context.Context, store database.RepoStore, db *da
if err != nil {
return nil, err
}
code := database.Code{
RepositoryID: rn.ID,
}
_, err = db.Core.NewInsert().Model(&code).Exec(ctx)
if err != nil {
return nil, err
}
for _, tag := range repo.Tags {
_, err = db.Core.NewInsert().Model(&tag).Exec(ctx, &tag)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions component/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ func (c *codeComponentImpl) Index(ctx context.Context, filter *types.RepoFilter,
break
}
}
if code == nil {
continue
}
var (
tags []types.RepoTag
mirrorTaskStatus types.MirrorTaskStatus
Expand Down
31 changes: 31 additions & 0 deletions component/code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,37 @@ func TestCodeComponent_Index(t *testing.T) {
}, data)
}

func TestCodeComponent_Index_HalfCreatedRepos(t *testing.T) {
ctx := context.TODO()
cc := initializeTestCodeComponent(ctx, t)

filter := &types.RepoFilter{Username: "user"}
// PublicToUser returns 3 repositories, but only 2 have corresponding codes
cc.mocks.components.repo.EXPECT().PublicToUser(ctx, types.CodeRepo, "user", filter, 10, 1).Return(
[]*database.Repository{
{ID: 1, Name: "r1", Tags: []database.Tag{{Name: "t1"}}},
{ID: 2, Name: "r2"},
{ID: 3, Name: "half-created", Tags: []database.Tag{{Name: "t3"}}}, // This is a half-created repo with no code
}, 3, nil, // Total should be 3
)

// ByRepoIDs returns only 2 codes (no code for repo ID 3)
cc.mocks.stores.CodeMock().EXPECT().ByRepoIDs(ctx, []int64{1, 2, 3}).Return([]database.Code{
{ID: 11, RepositoryID: 2, Repository: &database.Repository{ID: 2, Name: "r2", Mirror: database.Mirror{}}},
{ID: 12, RepositoryID: 1, Repository: &database.Repository{ID: 1, Name: "r1", Mirror: database.Mirror{}}},
}, nil)

data, total, err := cc.Index(ctx, filter, 10, 1, false)
require.Nil(t, err)
require.Equal(t, 3, total) // Total should match PublicToUser's return value
require.Len(t, data, 2) // But only 2 codes should be returned

require.Equal(t, []*types.Code{
{ID: 12, RepositoryID: 1, Name: "r1", Tags: []types.RepoTag{{Name: "t1"}}, RecomOpWeight: 0},
{ID: 11, RepositoryID: 2, Name: "r2", RecomOpWeight: 0},
}, data)
}

func TestCodeComponent_Update(t *testing.T) {
ctx := context.TODO()
cc := initializeTestCodeComponent(ctx, t)
Expand Down
49 changes: 49 additions & 0 deletions component/dataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,55 @@ func TestDatasetCompnent_Index(t *testing.T) {

}

func TestDatasetComponent_Index_HalfCreatedRepos(t *testing.T) {
ctx := context.TODO()
dc := initializeTestDatasetComponent(ctx, t)

filter := &types.RepoFilter{Username: "user"}
// PublicToUser returns 3 repositories, but only 2 have corresponding datasets
dc.mocks.components.repo.EXPECT().PublicToUser(ctx, types.DatasetRepo, "user", filter, 10, 1).Return(
[]*database.Repository{
{ID: 1, Tags: []database.Tag{{Name: "t1"}}},
{ID: 2},
{ID: 3, Tags: []database.Tag{{Name: "half-created"}}}, // This is a half-created repo with no dataset
}, 3, nil, // Total should be 3
)

// ByRepoIDs returns only 2 datasets (no dataset for repo ID 3)
dc.mocks.stores.DatasetMock().EXPECT().ByRepoIDs(ctx, []int64{1, 2, 3}).Return([]database.Dataset{
{
ID: 11, RepositoryID: 2, Repository: &database.Repository{
User: database.User{Username: "user2"},
},
},
{
ID: 12, RepositoryID: 1, Repository: &database.Repository{
User: database.User{Username: "user1"},
},
},
}, nil)

data, total, err := dc.Index(ctx, filter, 10, 1, false)
require.Nil(t, err)
require.Equal(t, 3, total) // Total should match PublicToUser's return value
require.Len(t, data, 2) // But only 2 datasets should be returned

require.Equal(t, []*types.Dataset{
{ID: 12, RepositoryID: 1, Repository: types.Repository{
HTTPCloneURL: "/s/.git",
SSHCloneURL: ":s/.git",
}, User: types.User{Username: "user1"},
Tags: []types.RepoTag{{Name: "t1"}},
},
{ID: 11, RepositoryID: 2, Repository: types.Repository{
HTTPCloneURL: "/s/.git",
SSHCloneURL: ":s/.git",
}, User: types.User{Username: "user2"},
},
}, data)

}

func TestDatasetCompnent_Update(t *testing.T) {
ctx := context.TODO()
dc := initializeTestDatasetComponent(ctx, t)
Expand Down
54 changes: 54 additions & 0 deletions component/mcp_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,60 @@ func TestMCPServerComponent_Index(t *testing.T) {
require.Equal(t, total, 1)
}

func TestMCPServerComponent_Index_HalfCreatedRepos(t *testing.T) {
ctx := context.TODO()
mc := initializeTestMCPServerComponent(ctx, t)

user := database.User{
Username: "user",
Email: "foo@bar.com",
}

// Create two repositories, one with complete data and one half-created
repo1 := &database.Repository{
ID: 321,
User: user,
Tags: []database.Tag{{Name: "t1"}},
Name: "complete-repo",
License: "MIT",
Nickname: "complete-repo",
Path: "ns/complete-repo",
}

repo2 := &database.Repository{
ID: 322,
User: user,
Tags: []database.Tag{{Name: "t2"}},
Name: "half-created",
License: "MIT",
Nickname: "half-created",
Path: "ns/half-created",
}

filter := &types.RepoFilter{
Username: "user",
}

// PublicToUser returns both repositories
mc.mocks.components.repo.EXPECT().PublicToUser(ctx, types.MCPServerRepo, "user", filter, 10, 1).
Return([]*database.Repository{repo1, repo2}, 2, nil)

// ByRepoIDs returns only 1 MCP server (no MCP server for repo2)
mc.mocks.stores.MCPServerMock().EXPECT().ByRepoIDs(ctx, []int64{321, 322}).Return([]database.MCPServer{
{
RepositoryID: 321,
Repository: repo1,
},
}, nil)

res, total, err := mc.Index(ctx, filter, 10, 1, false)
require.Nil(t, err)
require.NotNil(t, res)
require.Equal(t, total, 2) // Total should match PublicToUser's return value
require.Len(t, res, 1) // But only 1 MCP server should be returned
}


func TestMCPServerComponent_Properties(t *testing.T) {
ctx := context.TODO()
mc := initializeTestMCPServerComponent(ctx, t)
Expand Down
44 changes: 44 additions & 0 deletions component/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,50 @@ func TestModelComponent_Index(t *testing.T) {

}

func TestModelComponent_Index_HalfCreatedRepos(t *testing.T) {
ctx := context.TODO()
mc := initializeTestModelComponent(ctx, t)

filter := &types.RepoFilter{Username: "user"}
// PublicToUser returns 3 repositories, but only 2 have corresponding models
mc.mocks.components.repo.EXPECT().PublicToUser(ctx, types.ModelRepo, "user", filter, 10, 1).Return(
[]*database.Repository{
{ID: 1, Name: "r1", Tags: []database.Tag{{Name: "t1"}}},
{ID: 2, Name: "r2", Tags: []database.Tag{{Name: "t2"}}},
{ID: 3, Name: "half-created", Tags: []database.Tag{{Name: "t3"}}}, // This is a half-created repo with no model
}, 3, nil, // Total should be 3
)

// ByRepoIDs returns only 2 models (no model for repo ID 3)
mc.mocks.stores.ModelMock().EXPECT().ByRepoIDs(ctx, []int64{1, 2, 3}).Return([]database.Model{
{RepositoryID: 1, ID: 11, Repository: &database.Repository{}},
{RepositoryID: 2, ID: 12, Repository: &database.Repository{}},
}, nil)

data, total, err := mc.Index(ctx, filter, 10, 1, false)
require.Nil(t, err)
require.Equal(t, 3, total) // Total should match PublicToUser's return value
require.Len(t, data, 2) // But only 2 models should be returned

require.Equal(t, []*types.Model{
{
ID: 11, Name: "r1", Tags: []types.RepoTag{{Name: "t1"}}, RepositoryID: 1,
Repository: types.Repository{
HTTPCloneURL: "https://foo.com/s/.git",
SSHCloneURL: "test@127.0.0.1:s/.git",
},
},
{
ID: 12, Name: "r2", Tags: []types.RepoTag{{Name: "t2"}}, RepositoryID: 2,
Repository: types.Repository{
HTTPCloneURL: "https://foo.com/s/.git",
SSHCloneURL: "test@127.0.0.1:s/.git",
},
},
}, data)

}

func TestModelComponent_Create(t *testing.T) {
ctx := context.TODO()
mc := initializeTestModelComponent(ctx, t)
Expand Down
47 changes: 47 additions & 0 deletions component/prompt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,53 @@ func TestPromptComponent_IndexPromptRepo(t *testing.T) {

}

func TestPromptComponent_IndexPromptRepo_HalfCreatedRepos(t *testing.T) {
ctx := context.TODO()
pc := initializeTestPromptComponent(ctx, t)

filter := &types.RepoFilter{Username: "foo"}
// PublicToUser returns 4 repositories, but only 3 have corresponding prompts
pc.mocks.components.repo.EXPECT().PublicToUser(ctx, types.PromptRepo, "foo", filter, 10, 1).Return([]*database.Repository{
{ID: 1, Name: "rp1"},
{ID: 2, Name: "rp2"},
{ID: 3, Name: "rp3", Tags: []database.Tag{{Name: "t1"}}},
{ID: 4, Name: "half-created", Tags: []database.Tag{{Name: "t2"}}}, // This is a half-created repo with no prompt
}, 4, nil).Once()
// ByRepoIDs returns only 3 prompts (no prompt for repo ID 4)
pc.mocks.stores.PromptMock().EXPECT().ByRepoIDs(ctx, []int64{1, 2, 3, 4}).Return([]database.Prompt{
{ID: 6, RepositoryID: 2, Repository: &database.Repository{}},
{ID: 5, RepositoryID: 1, Repository: &database.Repository{}},
{ID: 4, RepositoryID: 3, Repository: &database.Repository{}},
}, nil).Once()

results, total, err := pc.IndexPromptRepo(ctx, filter, 10, 1)
require.Nil(t, err)
require.Equal(t, 4, total) // Total should match PublicToUser's return value
require.Len(t, results, 3) // But only 3 prompts should be returned

require.Equal(t, []types.PromptRes{
{
RepositoryID: 1,
ID: 5, Name: "rp1", Repository: types.Repository{
HTTPCloneURL: "",
SSHCloneURL: "",
}},
{
RepositoryID: 2,
ID: 6, Name: "rp2", Repository: types.Repository{
HTTPCloneURL: "",
SSHCloneURL: "",
}},
{
RepositoryID: 3,
ID: 4, Name: "rp3", Repository: types.Repository{
HTTPCloneURL: "",
SSHCloneURL: "",
}, Tags: []types.RepoTag{{Name: "t1"}}},
}, results)

}

func TestPromptComponent_UpdatePromptRepo(t *testing.T) {
ctx := context.TODO()
pc := initializeTestPromptComponent(ctx, t)
Expand Down
Loading
Loading