Thank you for your interest in contributing! This project is a Declarative Automation Bundles custom template, and contributions of all kinds are welcome: bug reports, feature requests, documentation improvements, and code changes.
- Python 3.11+
- Databricks CLI v0.296.0+ (installation guide)
- Fork the repository
- Clone your fork:
git clone https://github.com/<your-username>/databricks-bundle-template.git cd databricks-bundle-template
- Create and activate a virtual environment:
python -m venv venv source venv/bin/activate # Linux/macOS venv\Scripts\activate # Windows
- Install development dependencies:
pip install -r tests/requirements_dev.txt
- Run the test suite to verify your setup:
pytest tests/ -V
This is a Go template project consumed by the Databricks CLI via databricks bundle init. Key concepts:
databricks_template_schema.jsondefines interactive prompts users see during initializationlibrary/helpers.tmplcontains custom Go template helper functionstemplate/{{.project_name}}/contains all the Go template files that generate the user's projecttemplate/update_layout.tmplcontrols conditional file/directory generation (e.g., skip.azure/when GitHub Actions is selected)- Files ending in
.tmplare processed by the Go template engine; other files are copied as-is
The template has multiple parameters. Part of these are configuration axes that drive conditional logic and produce structurally different outputs:
| Parameter | Options | Effect |
|---|---|---|
environment_setup |
full / minimal |
3-4 targets vs 2 targets |
include_dev_environment |
yes / no |
Adds dev target (full mode only) |
compute_type |
classic / serverless / both |
Cluster config vs environments |
include_permissions |
yes / no |
RBAC blocks in all resources |
include_cicd |
yes / no |
CI/CD pipeline templates |
cicd_platform |
azure_devops / github_actions / gitlab |
Platform-specific pipeline |
cloud_provider |
azure / aws / gcp |
Auth method (ARM vs OAuth M2M) |
workspace_setup |
single_workspace / multi_workspace |
Workspace topology per environment |
The remaining parameters provide input values:
| Parameter | Purpose |
|---|---|
project_name |
Bundle name, folder name, resource prefixes |
uc_catalog_suffix |
Unity Catalog naming (dev_<suffix>, stage_<suffix>, prod_<suffix>) |
configure_sp_now |
Configure SP IDs during init or defer with SP_PLACEHOLDER |
dev/stage/prod_service_principal |
SP App IDs per environment (conditional on configure_sp_now) |
default_branch |
Branch for staging deployments (CI/CD only) |
release_branch |
Branch for prod deployments (CI/CD + full mode only) |
See ARCHITECTURE.md for detailed design decisions and conditional logic patterns.
When modifying template files under template/{{.project_name}}/:
- Use Go template syntax:
{{ .variable_name }},{{- if eq .var "value" }}...{{- end }} - Use
{{-to strip preceding whitespace and-}}to strip following whitespace - Use standard
{{ }}(without dashes) when whitespace must be preserved (e.g., inside sentences) - Test all affected configuration combinations
- Add the parameter to
databricks_template_schema.jsonwith appropriateorder,pattern, andskip_prompt_if - Add conditional logic in the relevant
.tmplfiles - Create new test config files in
tests/configs/if needed - Update existing tests or add new ones
- Create a JSON file in
tests/configs/with your parameter values - The test suite automatically picks up all config files via parametrized fixtures
# Run full test suite
pytest tests/ -V
# Run a specific test
pytest tests/test_generation.py::test_no_tmpl_files_remain -v
# Run tests for a specific file
pytest tests/test_content.py -v# Generate a project with a specific config
databricks bundle init . --output-dir ../test-output --config-file tests/configs/full_with_dev.json
# Validate the generated bundle (requires Databricks CLI auth)
cd ../test-output/test_full_with_dev/
databricks bundle validate -t userAll contributions must:
- Pass the full test suite (
pytest tests/ -V) - Include new tests for new functionality
- Not leave any
.tmplfiles in generated output
- Create a feature branch from
main:git checkout -b feature/your-feature-name
- Make your changes and run the full test suite
- Commit with a clear message describing what and why
- Push to your fork and open a Pull Request against
main - Fill out the PR template with the required information
- Keep PRs focused on a single change
- Include test results in the PR description
- If your change affects generated output, include a sample of the before/after
- Update documentation if behavior changes
Cutting a release (bumping the version, finalizing the changelog, tagging, and publishing a GitHub release) follows a dedicated checklist in RELEASING.md. The short version: the version bump and the [Unreleased] to [X.Y.Z] - <date> rename happen inside the PR before merge, so main is always release-ready; the annotated tag and the GitHub release happen after merge. A guard test (tests/test_release_metadata.py) keeps the two version markers and the changelog in sync.
The repository also ships an asset library: standalone sub-templates under assets/<asset-name>/ that install individual Databricks artifacts (pipelines, jobs, dashboards) via databricks bundle init --template-dir. See ASSETS.md for the end-user catalog and install pattern, and ARCHITECTURE.md §8 for the design rationale.
- Asset directory: kebab-case (
assets/<asset-name>/). The name appears in CLI commands (--template-dir assets/<asset-name>), so it should read naturally there. - Test file and config JSON: snake_case, derived from the asset name. Example: asset
sdp-checkpoint-recoverygetstests/assets/test_sdp_checkpoint_recovery.pyandtests/configs/assets/sdp_checkpoint_recovery.json. - Multiple configs for one asset: the default config is
<asset>.json. Additional variants use suffixes:<asset>_<variant>.json(for examplesdp_checkpoint_recovery.jsondefault,sdp_checkpoint_recovery_custom_target.jsonvariant). The asset name is always the prefix; parametrize tests over the variants explicitly.
Every asset must follow these seven rules:
- Self-contained. No references to files outside the asset directory. No shared
library/helpers.tmpl. If two assets need the same helper, each defines its own copy. Duplication is the price of portability. - Schema at minimum. An asset with no prompts still ships a
databricks_template_schema.jsondeclaringversionandmin_databricks_cli_version."properties": {}is valid. - Target path never collides with a conventional bundle. The asset installs under a predictable subdirectory that a fresh bundle would not already contain (
ops/<name>/,resources/<name>.yml, etc.). Prefer a{{.target_dir}}or{{.<artifact>_name}}prompt so the user can rename on install. - No modification of parent files. The CLI cannot edit existing files. If an integration requires a line change (e.g., adding an
include:glob todatabricks.yml), the asset's README states the exact one-liner. - Install command is canonical and identical per asset. Every asset README documents exactly:
databricks bundle init https://github.com/vmariiechko/databricks-bundle-template \ --template-dir assets/<asset-name>
- Tests are per-asset. Framework-level smoke checks (
tests/assets/test_framework.py) run automatically for everyassets/*/. Asset-specific deep tests live attests/assets/test_<asset_name>.pyand are added only when the asset has non-trivial structure to verify (exact file lists, YAML validity, Python parses, etc.). Both reuse theinstall_assetfixture fromtests/assets/conftest.py. - Single repo-wide CHANGELOG. No per-asset versioning for now. Changes are grouped under
[Unreleased]→### Added / ### Changed. At release time the[Unreleased]heading is renamed to[X.Y.Z] - <date>and a fresh empty[Unreleased]is added above it; see RELEASING.md.
-
Create the asset directory:
assets/<asset-name>/ ├── databricks_template_schema.json ├── README.md └── template/ └── <target-path-or-{{.target_dir}}>/ └── ...files...databricks_template_schema.json: prompt schema. See thesdp-checkpoint-recoveryasset for a minimal single-prompt example.README.md: asset-level: purpose, canonical install command, link to usage docs insidetemplate/.template/...: anything under this directory is what the user gets in their bundle. Use Go template variables for any user-parameterized paths (template/{{.target_dir}}/file.py) or file contents.
-
Add a test config at
tests/configs/assets/<asset_name_snake_case>.jsonwith the prompt values to use in automated tests. Use{}if the asset has no prompts. -
(Optional) Add asset-specific tests at
tests/assets/test_<asset_name_snake_case>.py. Use the sharedinstall_assetfixture fromtests/assets/conftest.py:def test_something(install_asset): output_dir = install_asset("<asset-name>", config="<asset_name>") # assert on output_dir contents
Framework-level smoke tests run automatically without any extra file.
-
Add a row to the catalog table in ASSETS.md.
-
Add an entry under
## [Unreleased]in CHANGELOG.md under### Added. The entry stays under[Unreleased]until a release finalizes it (see RELEASING.md); do not invent a version heading in your PR unless the PR itself cuts the release. -
Verify locally:
# The asset installs cleanly to a temp directory databricks bundle init ./assets/<asset-name> \ --output-dir /tmp/<asset-name>-test \ --config-file tests/configs/assets/<asset_name>.json # The full test suite still passes pytest tests/ -V
When opening a PR that introduces or modifies an asset:
- Asset has its own
databricks_template_schema.jsonandREADME.md - Framework smoke tests pass (
pytest tests/assets/test_framework.py -v) - Asset-specific tests pass (if added)
-
ASSETS.mdcatalog is updated -
CHANGELOG.mdhas an entry under[Unreleased](or, if this PR cuts the release, a finalized[X.Y.Z] - <date>entry per RELEASING.md) - No changes outside
assets/<asset-name>/,tests/assets/,tests/configs/assets/, and the four cross-reference docs (ASSETS.md,CHANGELOG.md,README.md, andROADMAP.mdif status changes)
- Bug reports: Use the bug report template
- Feature requests: Use the feature request template
- Questions: Use GitHub Discussions
- Go templates: Follow existing patterns in the codebase. Consistent use of whitespace control (
{{-/-}}) - Python (tests): Use ruff for linting and formatting
- YAML: 2-space indentation, consistent with Databricks conventions
This project is released with a Contributor Code of Conduct. By participating you agree to abide by its terms.
By contributing, you agree that your contributions will be licensed under the MIT License.