Skip to content

Recognize ssh:// template URLs in bundle init - #5891

Merged
janniklasrose merged 7 commits into
mainfrom
janniklasrose/bundle-init-git-clone-url
Jul 13, 2026
Merged

Recognize ssh:// template URLs in bundle init#5891
janniklasrose merged 7 commits into
mainfrom
janniklasrose/bundle-init-git-clone-url

Conversation

@janniklasrose

@janniklasrosejanniklasrose commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Changes

gitUrlPrefixes in libs/template/resolver.go only recognized https:// and git@, which is incomplete relative to the git URL spec. This adds ssh:// so databricks bundle init clones templates from SSH-transport URLs. git://, http://, and ftp[s]:// are deliberately excluded as deprecated/insecure protocols.

Also renames IsRepoUrl to IsGitRepoUrl and simplifies it to return directly on the first matching prefix.

Why

Closes#5881: SSH-transport template URLs were not recognized and fell through to the local-path reader. For non git@ prefixed SSH URLs customers could not use the command.

Tests

Unit test TestBundleInitIsGitRepoUrl updated to cover the supported (https://, ssh://, git@) and unsupported (git://, http://, ftp[s]://, local paths) forms. No acceptance test exercises git-URL detection.

This PR was written by Claude Code.

gitUrlPrefixes was incomplete relative to the git URL spec
(https://git-scm.com/docs/git-clone#_git_urls). Add ssh:// so that
`databricks bundle init` clones from SSH-transport URLs. Also rename
IsRepoUrl to IsGitRepoUrl and simplify it to return directly on match.
Fixes#5881
Co-authored-by: Isaac
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: c75c2e2

Run: 29204410462

Env🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
💚​aws linux4423010789:19
💚​aws windows4423210766:52
💚​aws-ucws linux443169955:30
🔄​aws-ucws windows1443179937:42
💚​azure linux4423010777:11
💚​azure windows4423210757:48
💚​azure-ucws linux4431899214:25
💚​azure-ucws windows443209907:26
💚​gcp linux4422910799:35
💚​gcp windows4423110777:34
9 interesting tests: 4 RECOVERED, 4 SKIP, 1 flaky
Test Nameaws linuxaws windowsaws-ucws linuxaws-ucws windowsazure linuxazure windowsazure-ucws linuxazure-ucws windowsgcp linuxgcp windows
💚​TestAccept💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
🙈​TestAccept/bundle/invariant/no_drift🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/ssh/connection🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🔄​TestSyncIncrementalFileOverwritesFolder✅​p✅​p✅​p🔄​f✅​p✅​p✅​p✅​p✅​p✅​p
💚​TestFetchRepositoryInfoAPI_FromRepo💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestFetchRepositoryInfoAPI_FromRepo/root💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestFetchRepositoryInfoAPI_FromRepo/subdir💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
Top 17 slowest tests (at least 2 minutes):
durationenvtestname
7:32gcp linuxTestSecretsPutSecretStringValue
7:04aws linuxTestSecretsPutSecretStringValue
6:44azure-ucws linuxTestSQLExecScalar
6:40gcp windowsTestAccept
6:40azure windowsTestAccept
6:32aws-ucws windowsTestAccept
6:16azure-ucws windowsTestAccept
5:54aws windowsTestAccept
4:51azure linuxTestSecretsPutSecretStringValue
4:40azure-ucws linuxTestSecretsPutSecretStringValue
3:35azure-ucws windowsTestSQLExecScalar
3:11gcp windowsTestSecretsPutSecretStringValue
2:59gcp linuxTestAccept
2:53azure linuxTestAccept
2:51aws linuxTestAccept
2:49azure-ucws linuxTestAccept
2:48aws-ucws linuxTestAccept

@shreyas-goenkashreyas-goenka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test that this works end to end? Just to confirm that there's no missing bit needed here? Because we don't have any test coverage for this case.

@janniklasrose
janniklasrose added this pull request to the merge queueJul 13, 2026
@janniklasrose

janniklasrose commented Jul 13, 2026

Copy link
Copy Markdown
ContributorAuthor

@shreyas-goenka yes, I did but didn't add to the test section:

./cli bundle init --template-dir libs/template/templates/default-scala git@github.com:databricks/cli.git
./cli bundle init --template-dir libs/template/templates/default-scala https://github.com/databricks/cli.git
./cli bundle init --template-dir libs/template/templates/default-scala ssh://git@github.com/databricks/cli.git

Testing the unhappy path revealed that the unsupported protocols (http://... etc) give a pretty cryptic error (that's pre-existing behaviour, they assume it's a local file path). Will send a separate fix to make that a bit nicer (& add an e2e acceptance test if possible)

Merged via the queue into main with commit da7bd2bJul 13, 2026
26 checks passed
@janniklasrose
janniklasrose deleted the janniklasrose/bundle-init-git-clone-url branch July 13, 2026 09:06
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: da7bd2b

Run: 29237837040

Env❌​FAIL🟨​KNOWN🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
❌​aws linux6134523101044:26
💚​aws windows44486102353:39
❌​aws-ucws linux111252990820172:52
❌​aws-ucws windows111632930838196:58
💚​azure linux44523101147:52
💚​azure windows44480102455:30
🔄​azure-ucws linux532896855161:35
🔄​azure-ucws windows462836873160:52
💚​gcp linux44514101646:00
💚​gcp windows44471102958:18
36 interesting tests: 17 FAIL, 15 flaky, 2 SKIP, 1 KNOWN, 1 RECOVERED
Test Nameaws linuxaws windowsaws-ucws linuxaws-ucws windowsazure linuxazure windowsazure-ucws linuxazure-ucws windowsgcp linuxgcp windows
🟨​TestAccept🟨​K💚​R🟨​K🟨​K💚​R💚​R🔄​f💚​R💚​R💚​R
🔄​TestAccept/bundle/invariant/no_drift🙈​S🙈​S💚​R🔄​f🙈​S🙈​S💚​R💚​R🙈​S🙈​S
🔄​TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=synced_database_table.yml.tmpl/READPLAN=✅​p🔄​f✅​p✅​p
🔄​TestAccept/bundle/resources/apps/lifecycle-started✅​p✅​p✅​p✅​p✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/dashboards/change-name✅​p✅​p✅​p🔄​f✅​p✅​p✅​p🔄​f✅​p✅​p
🔄​TestAccept/bundle/resources/dashboards/change-name/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p🔄​f✅​p✅​p✅​p✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/dashboards/change-name/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p✅​p✅​p✅​p🔄​f✅​p✅​p
🔄​TestAccept/bundle/resources/permissions/dashboards/create✅​p✅​p🔄​f✅​p✅​p✅​p✅​p✅​p🙈​s🙈​s
🔄​TestAccept/bundle/resources/permissions/dashboards/create/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p🔄​f✅​p✅​p✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions❌​F✅​p✅​p✅​p🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct❌​F✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform❌​F✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions❌​F✅​p✅​p✅​p🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct❌​F✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform❌​F✅​p✅​p✅​p
❌​TestAccept/bundle/resources/postgres_databases/live_errors/missing_role🙈​s🙈​s❌​F❌​F🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/postgres_databases/live_errors/missing_role/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/basic🙈​s🙈​s❌​F❌​F🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/postgres_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/replace_existing🙈​s🙈​s❌​F❌​F🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/postgres_endpoints/replace_existing/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/replace_existing/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/update_autoscaling🙈​s🙈​s❌​F❌​F🙈​s🙈​s🙈​s🙈​s🙈​s🙈​s
❌​TestAccept/bundle/resources/postgres_endpoints/update_autoscaling/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F
❌​TestAccept/bundle/resources/postgres_endpoints/update_autoscaling/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F
🔄​TestAccept/bundle/resources/quality_monitors/change_output_schema_name🙈​s🙈​s✅​p✅​p🙈​s🙈​s✅​p🔄​f🙈​s🙈​s
🔄​TestAccept/bundle/resources/quality_monitors/change_output_schema_name/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p🔄​f
🔄​TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name🙈​S🙈​S💚​R🔄​f🙈​S🙈​S💚​R💚​R🙈​S🙈​S
🔄​TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name/DATABRICKS_BUNDLE_ENGINE=direct✅​p🔄​f✅​p✅​p
🙈​TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/ssh/connection🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
💚​TestFetchRepositoryInfoAPI_FromRepo💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
🔄​TestFetchRepositoryInfoAPI_FromRepo/root💚​R💚​R💚​R💚​R💚​R💚​R🔄​f💚​R💚​R💚​R
🔄​TestFetchRepositoryInfoAPI_FromRepo/subdir💚​R💚​R💚​R💚​R💚​R💚​R🔄​f💚​R💚​R💚​R
Top 50 slowest tests (at least 2 minutes):
durationenvtestname
17:00aws-ucws linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
12:20gcp windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
12:06gcp linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
11:57gcp linuxTestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct
11:09aws-ucws windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
10:35azure-ucws linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
10:11aws-ucws windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:59aws-ucws linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:49aws-ucws linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
8:35azure-ucws windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:31aws-ucws linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
8:24azure-ucws windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:23gcp linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:04aws windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:03aws-ucws linuxTestAccept/bundle/resources/clusters/deploy/simple/DATABRICKS_BUNDLE_ENGINE=direct
7:35azure linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:35azure windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:24azure linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:21gcp windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:16aws linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:16aws linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
6:54gcp windowsTestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct
6:53aws windowsTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
6:38azure linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
6:30aws windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
6:25aws windowsTestAccept
6:22gcp windowsTestAccept
6:19azure windowsTestAccept
6:12aws-ucws linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct
6:06azure-ucws linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=terraform
6:05azure linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
6:04gcp linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
6:01aws-ucws windowsTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:59aws-ucws windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
5:58azure-ucws windowsTestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
5:51azure-ucws linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:39azure-ucws linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
5:37azure windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
5:36azure-ucws windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
5:29azure-ucws linuxTestAccept/bundle/resources/apps/lifecycle-started-omitted/DATABRICKS_BUNDLE_ENGINE=direct
5:22aws-ucws windowsTestAccept/bundle/resources/apps/lifecycle-started-omitted/DATABRICKS_BUNDLE_ENGINE=direct
5:16aws linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:16aws-ucws linuxTestAccept/bundle/resources/apps/lifecycle-started-omitted/DATABRICKS_BUNDLE_ENGINE=direct
5:15gcp windowsTestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:13aws linuxTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
5:12aws windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct
5:10aws linuxTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct
5:06aws-ucws linuxTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
4:59azure-ucws windowsTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
4:57azure-ucws linuxTestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct

bradleyjamrozik-origindigital pushed a commit to Origin-Digital-LLC/databricks-cli that referenced this pull request Jul 13, 2026
…atabricks#5902)
## Changes
`databricks bundle init <url>` with an unsupported protocol previously
fell through to the local-path reader and failed with a confusing error:
```
$ databricks bundle init http://github.com/databricks/cli.git
Error: not a bundle template: expected to find a template schema file at databricks_template_schema.json
```
Now the deprecated/insecure transports (`http://`, `git://`, `ftp://`,
`ftps://`) are recognized as Git URLs but flagged invalid, so
`ResolveReader` returns an actionable error naming the supported
protocols:
```
Error: unsupported protocol in Git URL "http://github.com/databricks/cli.git": only https://, ssh://, and git@ URLs are supported
```
`ResolveReader` now returns an `error`; both callers (`Resolver.Resolve`
and the `render-template-schema` debug command) propagate it.
## Why
Follow-up to databricks#5891. The fall-through behavior gave no hint that the
protocol was the problem.
## Tests
- Unit tests in `resolver_test.go` cover the invalid-protocol path in
`ResolveReader`.
- New acceptance test `bundle/templates-machinery/unsupported-url`
asserts the CLI error. The error is raised at resolve time, before any
network access, so no request mocking is needed.
_This PR was written by Claude Code._
deco-sdk-taggingBot added a commit that referenced this pull request Jul 15, 2026
## Release v1.8.0
### Notable Changes
* Auto-migrate a bundle from terraform to the direct engine when `bundle.engine` is `"direct"` (or `DATABRICKS_BUNDLE_ENGINE=direct`) and the post-deploy dry-run migration is clean; a warning is emitted if the dry-run surfaces errors or warnings so the automatic migration is skipped.
### CLI
* experimental `ssh connect`: bare `python`/`pip` in an interactive session now resolve to the environment interpreter (`$DATABRICKS_VIRTUAL_ENV`) instead of the system or cluster-libraries interpreter, so packages installed in the environment are importable without extra setup. The interactive shell is now non-login (`bash -i`) and the server seeds a `~/.bashrc` snippet that re-prepends the environment's bin directory to `PATH` ([#5888](#5888)).
* When Claude Code runs the CLI without the Databricks AI tooling installed, the CLI now prints a one-line recommendation on stderr to run `databricks aitools install`. The recommendation is shown at most once per hour per Claude session, and never for human callers or `aitools` commands.
* Fixed `databricks auth describe` misattributing a profile selected via `DATABRICKS_CONFIG_PROFILE` as `(from bundle)` when run inside a bundle root ([#5904](#5904)).
### Bundles
* `bundle generate` now warns when the generated configuration file is not matched by any pattern in the `include` section of `databricks.yml` ([#5868](#5868)).
* direct: Match UC Auto Upgrade managed property defaults with a wildcard pattern instead of enumerating each key ([#5877](#5877)).
* Recognize `ssh://` template URLs in `databricks bundle init` ([#5891](#5891)).
* `databricks bundle init` now reports an actionable error when given a template URL with an unsupported protocol (`http://`, `git://`, `ftp://`, `ftps://`) instead of failing with a confusing "not a bundle template" message ([#5902](#5902)).
* Added an `env:` section to `scripts.<name>` for declaring environment variables that may reference `${bundle.*}`, `${workspace.*}`, and `${var.*}` ([#4179](#4179), [#5299](#5299)).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cli bundle init ssh support

3 participants

@janniklasrose@eng-dev-ecosystem-bot@shreyas-goenka