Skip to content

Latest commit

 

History

History
248 lines (179 loc) · 12.4 KB

File metadata and controls

248 lines (179 loc) · 12.4 KB

Contributing to databricks-bundle-template

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.

Prerequisites

Getting Started

  1. Fork the repository
  2. Clone your fork:
    git clone https://github.com/<your-username>/databricks-bundle-template.git
    cd databricks-bundle-template
  3. Create and activate a virtual environment:
    python -m venv venv
    source venv/bin/activate    # Linux/macOS
    venv\Scripts\activate       # Windows
  4. Install development dependencies:
    pip install -r tests/requirements_dev.txt
  5. Run the test suite to verify your setup:
    pytest tests/ -V

How the Template Works

This is a Go template project consumed by the Databricks CLI via databricks bundle init. Key concepts:

  • databricks_template_schema.json defines interactive prompts users see during initialization
  • library/helpers.tmpl contains custom Go template helper functions
  • template/{{.project_name}}/ contains all the Go template files that generate the user's project
  • template/update_layout.tmpl controls conditional file/directory generation (e.g., skip .azure/ when GitHub Actions is selected)
  • Files ending in .tmpl are processed by the Go template engine; other files are copied as-is

Template Parameters

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.

Making Changes

Template Files

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

Adding a New Prompt

  1. Add the parameter to databricks_template_schema.json with appropriate order, pattern, and skip_prompt_if
  2. Add conditional logic in the relevant .tmpl files
  3. Create new test config files in tests/configs/ if needed
  4. Update existing tests or add new ones

Adding a New Test Configuration

  1. Create a JSON file in tests/configs/ with your parameter values
  2. The test suite automatically picks up all config files via parametrized fixtures

Testing

Running Tests

# 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

Manual Testing

# 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 user

Test Requirements

All contributions must:

  • Pass the full test suite (pytest tests/ -V)
  • Include new tests for new functionality
  • Not leave any .tmpl files in generated output

Submitting Changes

  1. Create a feature branch from main:
    git checkout -b feature/your-feature-name
  2. Make your changes and run the full test suite
  3. Commit with a clear message describing what and why
  4. Push to your fork and open a Pull Request against main
  5. Fill out the PR template with the required information

Pull Request Guidelines

  • 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

Releasing

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.

Adding an Asset

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.

Naming conventions

  • 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-recovery gets tests/assets/test_sdp_checkpoint_recovery.py and tests/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 example sdp_checkpoint_recovery.json default, sdp_checkpoint_recovery_custom_target.json variant). The asset name is always the prefix; parametrize tests over the variants explicitly.

Framework rules

Every asset must follow these seven rules:

  1. 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.
  2. Schema at minimum. An asset with no prompts still ships a databricks_template_schema.json declaring version and min_databricks_cli_version. "properties": {} is valid.
  3. 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.
  4. No modification of parent files. The CLI cannot edit existing files. If an integration requires a line change (e.g., adding an include: glob to databricks.yml), the asset's README states the exact one-liner.
  5. 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>
  6. Tests are per-asset. Framework-level smoke checks (tests/assets/test_framework.py) run automatically for every assets/*/. Asset-specific deep tests live at tests/assets/test_<asset_name>.py and are added only when the asset has non-trivial structure to verify (exact file lists, YAML validity, Python parses, etc.). Both reuse the install_asset fixture from tests/assets/conftest.py.
  7. 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.

Authoring walkthrough

  1. 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 the sdp-checkpoint-recovery asset for a minimal single-prompt example.
    • README.md: asset-level: purpose, canonical install command, link to usage docs inside template/.
    • 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.
  2. Add a test config at tests/configs/assets/<asset_name_snake_case>.json with the prompt values to use in automated tests. Use {} if the asset has no prompts.

  3. (Optional) Add asset-specific tests at tests/assets/test_<asset_name_snake_case>.py. Use the shared install_asset fixture from tests/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.

  4. Add a row to the catalog table in ASSETS.md.

  5. 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.

  6. 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

PR checklist for asset changes

When opening a PR that introduces or modifies an asset:

  • Asset has its own databricks_template_schema.json and README.md
  • Framework smoke tests pass (pytest tests/assets/test_framework.py -v)
  • Asset-specific tests pass (if added)
  • ASSETS.md catalog is updated
  • CHANGELOG.md has 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, and ROADMAP.md if status changes)

Reporting Issues

Code Style

  • 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

Code of Conduct & License

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.