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:
-
Install the GitHub CLI if you haven’t already. Visit https://cli.github.com/.
-
Authenticate with your GitHub account by running:
-
Create a new codespace for this repository using the following command:
-
Once the codespace is created, you can connect to it via VS Code or
sshinto it: -
Inside the workspace, sync the locked Python environment:
Run project commands through the environment with
uv run, for example:
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:
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:orwith 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:
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.