From cb135fc4e48f334035c2b2b03f4305c89bce84af Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Thu, 11 Jun 2026 20:16:50 +0200 Subject: [PATCH] Improve error for labs projects that do not provide labs.yml Most repositories in the databrickslabs GitHub org do not ship a labs.yml manifest and thus cannot be installed via the CLI. Installing one of them (e.g. 'databricks labs install brickster') failed with the cryptic 'Error: remote: read labs.yml from GitHub: not found'. Detect the not-found case and explain that the project is not installable with the CLI, pointing at the repository for instructions. Co-authored-by: Isaac --- cmd/labs/project/fetcher.go | 8 ++++++++ cmd/labs/project/fetcher_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 cmd/labs/project/fetcher_test.go diff --git a/cmd/labs/project/fetcher.go b/cmd/labs/project/fetcher.go index c6969ae1ba7..53a9fa85315 100644 --- a/cmd/labs/project/fetcher.go +++ b/cmd/labs/project/fetcher.go @@ -151,6 +151,14 @@ func (f *fetcher) loadRemoteProjectDefinition(cmd *cobra.Command, version string var err error if !offlineInstall { raw, err = github.ReadFileFromRef(ctx, "databrickslabs", f.name, version, "labs.yml") + // Most repositories in the databrickslabs org don't ship a labs.yml manifest + // (e.g. libraries published to package indexes), so a missing file means the + // project isn't installable through the CLI, not that the download failed. + if errors.Is(err, github.ErrNotFound) { + return nil, fmt.Errorf("databrickslabs/%s@%s does not provide labs.yml (%w); "+ + "this project cannot be installed with the Databricks CLI, "+ + "see https://github.com/databrickslabs/%s for instructions", f.name, version, err, f.name) + } if err != nil { return nil, fmt.Errorf("read labs.yml from GitHub: %w", err) } diff --git a/cmd/labs/project/fetcher_test.go b/cmd/labs/project/fetcher_test.go new file mode 100644 index 00000000000..d2eb6427559 --- /dev/null +++ b/cmd/labs/project/fetcher_test.go @@ -0,0 +1,30 @@ +package project_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/databricks/cli/cmd/labs/github" + "github.com/databricks/cli/internal/testcli" + "github.com/stretchr/testify/assert" +) + +func TestInstallerFailsForProjectWithoutLabsYml(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/databrickslabs/blueprint/v0.3.15/labs.yml" { + w.WriteHeader(http.StatusNotFound) + return + } + t.Logf("Requested: %s", r.URL.Path) + t.FailNow() + })) + defer server.Close() + ctx := installerContext(t, server) + + r := testcli.NewRunner(t, ctx, "labs", "install", "blueprint") + _, _, err := r.Run() + assert.ErrorIs(t, err, github.ErrNotFound) + assert.ErrorContains(t, err, "databrickslabs/blueprint@v0.3.15 does not provide labs.yml") + assert.ErrorContains(t, err, "cannot be installed with the Databricks CLI") +}