Skip to content

Contributing to buildzr

Thank you for considering contributing to buildzr! Your help is greatly appreciated. Below are some guidelines to help you get started.

Happy Hacking 👩‍💻!

Getting Started

Codespaces

I recommend using GitHub Codespaces for development. Codespaces provides a consistent development environment and simplifies the setup process.

You can quickly set up and start contributing to our project using GitHub Codespaces via GitHub CLI. Follow these steps:

  1. Install the GitHub CLI if you haven’t already. Visit https://cli.github.com/.

  2. Authenticate with your GitHub account by running:

    gh auth login
    
  3. Create a new codespace for this repository using the following command:

    gh codespace create -r amirulmenjeni/buildzr
    
  4. Once the codespace is created, you can connect to it via VS Code or ssh into it:

    gh codespace ssh
    
  5. Inside the workspace, sync the locked Python environment:

    uv sync --all-extras --locked
    

    Run project commands through the environment with uv run, for example:

    uv run pytest --mypy tests
    

The codespace environment also includes useful tools developed by the Structurizr team such as Structurizr CLI, Structurizr Lite, and Structurizr On-Premises to view diagrams defined in Structurizr DSL or JSON. They’re mostly helpful during development to validate the Structurizr JSON schema generated by buildzr.

Running Tests

All tests are located in the tests folder. To run the tests, use the following command:

uv run pytest --mypy tests

Testing buildzr Samples

Sometimes it is valuable to manually check the output of the Structurizr workspace generated by buildzr visually. For this reason, you can create buildzr samples in the tests/samples directory.

Here’s an example of a simple workspace to showcase the group feature in Structurizr DSL used for grouping elements together:

from buildzr.dsl import (
    Workspace,
    SoftwareSystem,
    Container,
    Component,
    Group,
    SystemLandscapeView,
    SystemContextView,
    ContainerView,
)

with Workspace("w") as w:
    with Group("Company 1"):
        system_a = SoftwareSystem("A")
        with system_a:
            a1 = Container("a1")
            a2 = Container("a2")

    with Group("Company 2"):
        system_b = SoftwareSystem("B")
        with system_b:
            b1 = Container("b1")
            b2 = Container("b2")
            with b2:
                c1 = Component("c1")

    system_c = SoftwareSystem("C")

    # Define relationships
    system_a >> "Uses" >> system_b
    a1 >> "Uses" >> b1
    system_a >> "Uses" >> system_c

    # Create views
    SystemLandscapeView(
        key='groups-sample',
        description="Groups Sample"
    )

    SystemContextView(
        software_system_selector=system_a,
        key='groups-sample-a',
        description="Groups Sample - Software System A"
    )

    SystemContextView(
        software_system_selector=system_b,
        key='groups-sample-b',
        description="Groups Sample - Software System B"
    )

    ContainerView(
        software_system_selector=system_b,
        key='groups-sample-b2',
        description="Groups Sample - Container B2"
    )

    # Export to JSON
    w.to_json('groups-sample.json')

The example above demonstrates the current buildzr API using context managers (with statements) for a cleaner, more Pythonic syntax. Key features shown:

  • Use with Workspace("name") as w: to create a workspace context
  • Use with Group("name"): to group elements together
  • Use with software_system: or with container: to nest containers and components
  • Define relationships using the >> operator
  • Views and styles are created within the workspace context
  • Export using w.to_json('filename.json')

You can run this code directly or create sample files in the tests/samples directory for testing purposes.

Working with the .json files

What can you do with the generated .json files?

As mentioned, the .json file, if successfully and correctly generated using buildzr, should follow the Structurizr JSON schema. Thus you can make use of existing and mature Structurizr tools such as the Structurizr CLI and Structurizr Lite.

If you use codespaces (highly recommended), these tools are already pre-installed in the devcontainer image.

For example, to export the tests/samples/.tests.samples.groups.json to other format (say, PlantUML):

structurizr.sh \
    export \
    --format plantuml \
    --workspace tests/samples/.tests.samples.groups.json \
    --output tests/samples/.tests.samples.groups.puml

To view the rendering of tests/samples/.tests.samples.groups.json in the browser at http://localhost:8080:

structurizr-lite.sh tests/samples/.tests.samples.groups.json

Using Structurizr On-Premises

Structurizr On-Premises provides a full-featured workspace server with API support, allowing you to publish and manage multiple workspaces. This is useful for testing workspace publishing, API integration, and multi-workspace scenarios.

The codespace includes a helper script to run Structurizr On-Premises via Docker:

# Start Structurizr On-Premises (available at http://localhost:8080)
structurizr-onpremises.sh start

# Check status
structurizr-onpremises.sh status

# View logs
structurizr-onpremises.sh logs

# Stop the server
structurizr-onpremises.sh stop

Default credentials: structurizr / password

Once running, you can publish workspaces using the Structurizr CLI:

# Publish a workspace
structurizr.sh push \
    -id 1 \
    -key YOUR_API_KEY \
    -secret YOUR_API_SECRET \
    -workspace workspace.json \
    -url http://localhost:8080/api

Data is persisted in ~/.structurizr-onpremises/ so your workspaces survive container restarts.

Submitting Changes

As usual, just fork the repo, make changes, and submit PRs!

Releasing

Releases are published from master by the release workflow. To cut a release, open a pull request that sets a final version (for example 0.0.33) in buildzr/__about__.py. Once it is merged, the workflow builds the package, publishes it to PyPI, and pushes the v0.0.33 tag. It never pushes commits to master.

Every push to master runs the workflow, but it only releases when the version is final and its tag does not exist yet. Development, pre-release and post-release versions such as 0.0.33.dev0, 0.0.33rc1 or 0.0.33.post1 are skipped, so bumping to .dev0 does not trigger a release.

When a pull request changes the version, the check_version job of the build workflow validates it before merging: it fails on a version that is not canonical PEP 440 (for example 0.0.033), on a final version that is already tagged, and on a version that is not higher than the latest v* tag. Otherwise it reports whether merging will release the version to PyPI.

If a release fails, no tag is pushed. Re-run the failed run from the Actions tab before merging anything else; otherwise the next push to master releases that version from the newer commit. Files already on PyPI are skipped, so a re-run after a failed tag push only pushes the tag. A version that reached PyPI cannot be uploaded again: fix forward with a new version.