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

    ```bash
    gh auth login
    ```

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

    ```bash
    gh codespace create -r amirulmenjeni/buildzr -b feature/my-aweseome-contrib
    ```

4. Once the codespace is created, you can [connect to it via VS Code](https://docs.github.com/en/codespaces/developing-in-a-codespace/using-github-codespaces-in-visual-studio-code#opening-a-codespace-in-vs-code) or `ssh`
   into it:

    ```bash
    gh codespace ssh
    ```

5. Inside the workspace, setup and activate the Python environment:

    ```bash
    conda env create -f environment.yml
    ```

    To activate:

    ```bash
    conda activate buildzr-dev
    ```

The codespace environment also includes useful tools developed by the Structurizr team such as [Structurizr CLI](https://docs.structurizr.com/cli) and [Structurizr Lite](https://docs.structurizr.com/lite) to view diagrams defined in [Structurizr DSL](https://docs.structurizr.com/dsl) or [JSON](https://structurizr.com/json). They're mostly helpful during development to validate the [Structurizr JSON schema](https://github.com/structurizr/json) generated by `buildzr`.

### Running Tests

All tests are located in the `tests` folder. To run the tests, use the following command:
```sh
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`](https://github.com/amirulmenjeni/buildzr/tree/master/tests/samples) directory.

Here's an example of the [`GroupSample`](https://github.com/amirulmenjeni/buildzr/blob/master/tests/samples/groups.py), to showcase the [group](https://docs.structurizr.com/dsl/cookbook/groups/) feature in Structurizr DSL used for grouping elements together:

```python
import buildzr
from buildzr.dsl import *
from ..abstract_builder import AbstractBuilder

class GroupsSample(AbstractBuilder):

    def build(self) -> buildzr.models.Workspace:

        w = Workspace("w", scope=None)\
            .contains(
                Group(
                    "Company 1",
                    SoftwareSystem("A")\
                    .contains(
                        Container("a1"),
                        Container("a2"),
                    )
                ),
                Group(
                    "Company 2",
                    SoftwareSystem("B")\
                    .contains(
                        Container("b1"),
                        Container("b2")
                        .contains(
                            Component("c1"),
                        )
                    )
                ),
                SoftwareSystem("C"),
            )\
            .where(lambda w: [
                w.software_system().a >> "Uses" >> w.software_system().b,
                w.software_system().a.container().a1 >> "Uses" >> w.software_system().b.container().b1,
                w.software_system().a >> "Uses" >> w.software_system().c,
            ])\
            .with_views(
                SystemLandscapeView(
                    key='groups-sample',
                    description="Groups Sample"
                ),
                SystemContextView(
                    key='groups-sample-a',
                    software_system_selector=lambda w: cast(SoftwareSystem, w.a),
                    description="Groups Sample - Software System A"
                ),
                SystemContextView(
                    key='groups-sample-b',
                    software_system_selector=lambda w: cast(SoftwareSystem, w.b),
                    description="Groups Sample - Software System B"
                ),
                ContainerView(
                    key='groups-sample-b2',
                    software_system_selector=lambda w: w.software_system().b,
                    description="Groups Sample - Container B2"
                ),
            )\
            .get_workspace()

        return w.model
```

By running `pytest tests/test_workspaces.py`, all the sample workspaces would be built, creating the corresponding JSON file with Structurizr schema. In the case of the `GroupSample` class, for example, the resulting output file path would be `tests/samples/.tests.samples.groups.json` -- named after the name of the Python file that contains the `GroupSample` class.

Note that the sample class must inherit the `AbstractBuilder` class.

### 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](https://docs.structurizr.com/cli) and [Structurizr Lite](https://docs.structurizr.com/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](https://plantuml.com/)):

```bash
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:

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

## Submitting Changes

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