diff --git a/pkg/api/provider.go b/pkg/api/provider.go index ce5b11a..5487485 100644 --- a/pkg/api/provider.go +++ b/pkg/api/provider.go @@ -490,7 +490,12 @@ func (p *ScmProvider) listRegistry(c *gin.Context) { return } - repoList := p.registry.List() + repoList, err := p.registry.TopologicalOrder() + if err != nil { + // Keep the endpoint usable if the registry is malformed. + repoList = p.registry.List() + } + summaries := make([]repoSummary, 0, len(repoList)) for _, r := range repoList { summaries = append(summaries, repoSummary{ diff --git a/pkg/api/provider_test.go b/pkg/api/provider_test.go index da35a0a..55019b9 100644 --- a/pkg/api/provider_test.go +++ b/pkg/api/provider_test.go @@ -11,8 +11,10 @@ import ( "testing" goapi "dappco.re/go/core/api" + "dappco.re/go/core/io" "dappco.re/go/core/scm/marketplace" scmapi "dappco.re/go/core/scm/pkg/api" + "dappco.re/go/core/scm/repos" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -216,6 +218,39 @@ func TestScmProvider_ListRegistry_NilRegistry_Good(t *testing.T) { assert.Empty(t, resp.Data) } +func TestScmProvider_ListRegistry_TopologicalOrder_Good(t *testing.T) { + medium := io.NewMockMedium() + require.NoError(t, medium.Write("/tmp/repos.yaml", ` +version: 1 +org: host-uk +base_path: /tmp/repos +repos: + core-php: + type: foundation + core-admin: + type: module + depends_on: [core-php] +`)) + + reg, err := repos.LoadRegistry(medium, "/tmp/repos.yaml") + require.NoError(t, err) + + p := scmapi.NewProvider(nil, nil, reg, nil) + r := setupRouter(p) + w := httptest.NewRecorder() + req, _ := http.NewRequest("GET", "/api/v1/scm/registry", nil) + r.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code) + + var resp goapi.Response[[]map[string]any] + err = json.Unmarshal(w.Body.Bytes(), &resp) + require.NoError(t, err) + require.Len(t, resp.Data, 2) + assert.Equal(t, "core-php", resp.Data[0]["name"]) + assert.Equal(t, "core-admin", resp.Data[1]["name"]) +} + func TestScmProvider_RefreshMarketplace_Good(t *testing.T) { dir := t.TempDir() indexPath := filepath.Join(dir, "index.json")