Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bundle:
name: test-bundle
git:
origin_url: https://user:token@github.com/databricks/cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cloud = false
EnvMatrix.DMS = [""]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Files: 1 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 0 unchanged

>>> cat [OUTPUT_DIR]/out.requests.txt
{
"git": {
"origin_url": "https://github.com/databricks/cli"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
trace $CLI bundle deploy

trace cat "$OUT_REQUESTS" | jq 'select(has("path") and .path == "/telemetry-ext") | .body.protoLogs[] | fromjson | .entry.databricks_cli_log.bundle_deploy_event | {git}'

rm "$OUT_REQUESTS"
8 changes: 5 additions & 3 deletions bundle/phases/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/databricks/cli/bundle/metrics"
"github.com/databricks/cli/libs/dbr"
"github.com/databricks/cli/libs/dyn"
libgit "github.com/databricks/cli/libs/git"
"github.com/databricks/cli/libs/log"
"github.com/databricks/cli/libs/telemetry"
"github.com/databricks/cli/libs/telemetry/protos"
Expand Down Expand Up @@ -232,15 +233,16 @@ func pydabsMetrics(b *bundle.Bundle) *protos.BundleDeployPydabs {
}

// bundleGitInfo builds the git metadata for the deploy event, or nil when the
// bundle root is not inside a git repository. OriginURL already has credentials
// stripped by the load_git_details mutator.
// bundle root is not inside a git repository. OriginURL is stripped here because
// only the local .git route strips it upstream; a value from bundle.git.origin_url
// or from the workspace API for a Git folder is passed through as written.
func bundleGitInfo(b *bundle.Bundle) *protos.BundleGitInfo {
git := b.Config.Bundle.Git
if git.Branch == "" && git.Commit == "" && git.OriginURL == "" {
return nil
}
return &protos.BundleGitInfo{
OriginURL: git.OriginURL,
OriginURL: libgit.StripURLCredentials(git.OriginURL),
Branch: git.Branch,
Commit: git.Commit,
}
Expand Down
17 changes: 17 additions & 0 deletions bundle/phases/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,20 @@ func TestPydabsMetrics(t *testing.T) {
b := &bundle.Bundle{Config: config.Root{Experimental: &config.Experimental{Python: pythonConfig}}, Metrics: metrics}
assert.Equal(t, expected, pydabsMetrics(b))
}

func TestBundleGitInfoStripsOriginURLCredentials(t *testing.T) {
tests := []struct {
originURL string
want string
}{
{"https://user:token@github.com/databricks/cli", "https://github.com/databricks/cli"},
{"https://github.com/databricks/cli", "https://github.com/databricks/cli"},
}
for _, tt := range tests {
t.Run(tt.originURL, func(t *testing.T) {
b := &bundle.Bundle{}
b.Config.Bundle.Git.OriginURL = tt.originURL
assert.Equal(t, tt.want, bundleGitInfo(b).OriginURL)
})
}
}
11 changes: 9 additions & 2 deletions libs/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ func (r *Repository) LatestCommit() (string, error) {

// return origin url if it's defined, otherwise an empty string
func (r *Repository) OriginUrl() string {
rawUrl := r.config.variables["remote.origin.url"]
return StripURLCredentials(r.config.variables["remote.origin.url"])
}

// Remove username and password from the URL.
// StripURLCredentials removes the username and password from a URL.
func StripURLCredentials(rawUrl string) string {
parsedUrl, err := url.Parse(rawUrl)
if err != nil {
// Git supports https URLs and non standard URLs like "ssh://" or "file://".
Expand All @@ -118,6 +120,11 @@ func (r *Repository) OriginUrl() string {
// because passwords cannot be included in the URL.
return rawUrl
}
// Leave URLs without credentials as written; re-serializing can rewrite
// them (e.g. escaping spaces).
if parsedUrl.User == nil {
return rawUrl
}
// Setting User to nil removes the username and password from the URL when
// .String() is called.
// See: https://pkg.go.dev/net/url#URL.String
Expand Down
18 changes: 18 additions & 0 deletions libs/git/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,21 @@ func TestRepositoryOriginUrlRemovesUserCreds(t *testing.T) {
repo.assertOriginUrl(tc.expected)
}
}

func TestStripURLCredentials(t *testing.T) {
cases := []struct {
in string
want string
}{
{"https://user:pass@proxy.example/simple", "https://proxy.example/simple"},
{"https://token@proxy.example/simple", "https://proxy.example/simple"},
{"https://proxy.example/simple", "https://proxy.example/simple"},
{"ssh://git@github.com/databricks/cli.git", "ssh://github.com/databricks/cli.git"},
{"git@github.com:databricks/cli.git", "git@github.com:databricks/cli.git"},
{"not a url", "not a url"},
{"", ""},
}
for _, tc := range cases {
assert.Equal(t, tc.want, StripURLCredentials(tc.in))
}
}
Loading