diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..b1cf4d1
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,53 @@
+name: Release
+
+on:
+ workflow_dispatch:
+
+jobs:
+ # Build Python package
+ build:
+ uses: ewoks-kit/.github/.github/workflows/python-build.yml@main
+
+ # Run tests
+ tests:
+ needs: build
+ uses: ewoks-kit/.github/.github/workflows/python-tests.yml@main
+
+
+ # Publish package to TestPyPI
+ publish-testpypi:
+ needs: tests
+ runs-on: ubuntu-latest
+ environment:
+ name: release
+ permissions:
+ id-token: write
+ steps:
+ - uses: ewoks-kit/.github/.github/actions/setup-python-package@main
+ - uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ repository-url: https://test.pypi.org/legacy/
+
+ # Publish package to PyPI
+ publish-pypi:
+ needs: tests
+ runs-on: ubuntu-latest
+ environment:
+ name: release
+ permissions:
+ id-token: write
+ steps:
+ - uses: ewoks-kit/.github/.github/actions/setup-python-package@main
+ - uses: pypa/gh-action-pypi-publish@release/v1
+
+ # Tag
+ tag-release:
+ needs: publish-pypi
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - uses: ewoks-kit/.github/.github/actions/setup-python-package@main
+ - uses: ewoks-kit/.github/.github/actions/tag-release@main
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..0bc8c97
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,53 @@
+name: Test
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ workflow_dispatch:
+ workflow_call:
+
+jobs:
+ # Build Python package
+ build:
+ uses: ewoks-kit/.github/.github/workflows/python-build.yml@main
+
+ # Run tests
+ tests:
+ needs: build
+ uses: ewoks-kit/.github/.github/workflows/python-tests.yml@main
+ secrets:
+ codecov_token: ${{ secrets.CODECOV_TOKEN }}
+ with:
+ os: ${{ matrix.os }}
+ python-version: ${{ matrix.python-version }}
+ enable-coverage: ${{ matrix.enable-coverage }}
+ jupyter-platform-dirs: "1"
+ codecov-flags: "unit"
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: ubuntu-latest
+ python-version: "3.9"
+ enable-coverage: "false"
+ # https://github.com/networkx/networkx/issues/7372
+ extra-pytest-warnings: "-W ignore::RuntimeWarning:networkx.utils.backends"
+
+ - os: ubuntu-latest
+ python-version: "3.12"
+ enable-coverage: "true"
+ extra-pytest-warnings: ""
+
+
+ - os: windows-latest
+ python-version: "3.12"
+ enable-coverage: "false"
+ extra-pytest-warnings: ""
+
+ # Run linter / checks
+ checks:
+ uses: ewoks-kit/.github/.github/workflows/python-check.yml@main
+ with:
+ enable-isort: "false"
diff --git a/.gitignore b/.gitignore
index 2bba7ec..7973ac4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
!.readthedocs.yaml
!.flake8
!.flake8_nb
+!.github
# Byte / compiled / optimized
*.py[cod]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e69de29..210bbb7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -0,0 +1,24 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+### Added
+
+- CLI entry point `ewoksdraw` that generates an SVG file from a single output path argument.
+- Automatic mock workflow generation with a background and randomly positioned task blocks.
+- SVG task rendering with:
+ - task title text
+ - task box and title separator line
+ - input/output labels
+ - circular anchor links for IO ports
+- Adaptive task layout logic that scales/truncates text and adjusts font sizes to keep content within box width constraints.
+- SVG canvas export helpers:
+ - pretty-printed SVG file output
+ - in-memory XML representation
+ - dictionary representation via `xmltodict`
+- Basic CLI smoke test ensuring `ewoksdraw` writes an SVG output file.
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0bbc69a..e139321 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1 +1 @@
-CONTRIBUTING.md
\ No newline at end of file
+CONTRIBUTING.md
\ No newline at end of file
diff --git a/README.md b/README.md
index 74efbf0..d7f3c76 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
# ewoksdraw
+[](https://github.com/ewoks-kit/ewoksdraw/actions/workflows/test.yml)
+[](https://github.com/psf/black)
+[](https://github.com/ewoks-kit/ewoksdraw/blob/main/LICENSE.md)
+[](https://codecov.io/gh/ewoks-kit/ewoksdraw)
+
A project to generate SVG mock-ups out of Ewoks workflows.
## Quick start
diff --git a/pyproject.toml b/pyproject.toml
index 7085113..f6b552d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -37,7 +37,8 @@ test = [
]
dev = [
"pytest >=7",
- "ruff",
+ "ruff",
+ "black",
"mypy",
]
doc = [
@@ -76,7 +77,4 @@ ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "setuptools.*"
-ignore_missing_imports = true
-
-[tool.pytest.ini_options]
-addopts = "--cov=ewoksdraw --cov-report=term"
\ No newline at end of file
+ignore_missing_imports = true
\ No newline at end of file
diff --git a/src/ewoksdraw/main.py b/src/ewoksdraw/main.py
index 11956bc..6b4c0f8 100644
--- a/src/ewoksdraw/main.py
+++ b/src/ewoksdraw/main.py
@@ -3,9 +3,7 @@
from faker import Faker
-from .svg import SvgBackground
-from .svg import SvgCanvas
-from .svg import SvgTask
+from .svg import SvgBackground, SvgCanvas, SvgTask
def generate_random_names() -> list:
diff --git a/src/ewoksdraw/svg/svg_canvas.py b/src/ewoksdraw/svg/svg_canvas.py
index 6a79b9f..7aa4080 100644
--- a/src/ewoksdraw/svg/svg_canvas.py
+++ b/src/ewoksdraw/svg/svg_canvas.py
@@ -1,10 +1,7 @@
from pathlib import Path
-from typing import Iterator
-from typing import List
-from typing import Union
+from typing import Iterator, List, Union
from xml.dom import minidom
-from xml.etree.ElementTree import Element
-from xml.etree.ElementTree import tostring
+from xml.etree.ElementTree import Element, tostring
import xmltodict
diff --git a/src/ewoksdraw/svg/svg_element.py b/src/ewoksdraw/svg/svg_element.py
index 0ca1c50..dc25aee 100644
--- a/src/ewoksdraw/svg/svg_element.py
+++ b/src/ewoksdraw/svg/svg_element.py
@@ -1,6 +1,5 @@
from pathlib import Path
-from typing import Literal
-from typing import Optional
+from typing import Literal, Optional
from xml.etree.ElementTree import Element
diff --git a/src/ewoksdraw/svg/svg_group.py b/src/ewoksdraw/svg/svg_group.py
index df937d3..533fed0 100644
--- a/src/ewoksdraw/svg/svg_group.py
+++ b/src/ewoksdraw/svg/svg_group.py
@@ -1,6 +1,5 @@
import re
-from typing import Iterable
-from typing import Union
+from typing import Iterable, Union
from xml.etree.ElementTree import Element
from .svg_element import SvgElement
diff --git a/src/ewoksdraw/svg/svg_task.py b/src/ewoksdraw/svg/svg_task.py
index da077ce..4ee5e28 100644
--- a/src/ewoksdraw/svg/svg_task.py
+++ b/src/ewoksdraw/svg/svg_task.py
@@ -1,5 +1,4 @@
-from ..config.constants import IO_INTER_IO_MARGIN
-from ..config.constants import IO_TOP_MARGIN
+from ..config.constants import IO_INTER_IO_MARGIN, IO_TOP_MARGIN
from .svg_group import SvgGroup
from .svg_task_box import SvgTaskBox
from .svg_task_io import SvgTaskIOGroup
diff --git a/src/ewoksdraw/svg/svg_task_box.py b/src/ewoksdraw/svg/svg_task_box.py
index bca00df..e735f3a 100644
--- a/src/ewoksdraw/svg/svg_task_box.py
+++ b/src/ewoksdraw/svg/svg_task_box.py
@@ -1,5 +1,4 @@
-from ..config.constants import BOX_MAX_WIDTH
-from ..config.constants import BOX_MIN_WIDTH
+from ..config.constants import BOX_MAX_WIDTH, BOX_MIN_WIDTH
from .svg_element import SvgElement
diff --git a/src/ewoksdraw/svg/svg_task_io.py b/src/ewoksdraw/svg/svg_task_io.py
index 0ea43d3..7763a52 100644
--- a/src/ewoksdraw/svg/svg_task_io.py
+++ b/src/ewoksdraw/svg/svg_task_io.py
@@ -1,9 +1,11 @@
from typing import Literal
-from ..config.constants import ANCHOR_LINKS_RADIUS
-from ..config.constants import IO_ANCHOR_TEXT_MARGIN
-from ..config.constants import IO_MIN_FONT_SIZE
-from ..config.constants import IO_TARGET_FONT_SIZE
+from ..config.constants import (
+ ANCHOR_LINKS_RADIUS,
+ IO_ANCHOR_TEXT_MARGIN,
+ IO_MIN_FONT_SIZE,
+ IO_TARGET_FONT_SIZE,
+)
from .svg_group import SvgGroup
from .svg_task_anchor_link import SvgTaskAnchorLink
from .svg_text import SvgText
diff --git a/src/ewoksdraw/svg/svg_task_title.py b/src/ewoksdraw/svg/svg_task_title.py
index fc5888a..60c6e93 100644
--- a/src/ewoksdraw/svg/svg_task_title.py
+++ b/src/ewoksdraw/svg/svg_task_title.py
@@ -1,9 +1,11 @@
from typing import Optional
-from ..config.constants import TITLE_HORIZONTAL_MARGIN
-from ..config.constants import TITLE_MIN_FONT_SIZE
-from ..config.constants import TITLE_TARGET_FONT_SIZE
-from ..config.constants import TITLE_VERTICAL_MARGIN
+from ..config.constants import (
+ TITLE_HORIZONTAL_MARGIN,
+ TITLE_MIN_FONT_SIZE,
+ TITLE_TARGET_FONT_SIZE,
+ TITLE_VERTICAL_MARGIN,
+)
from .svg_text import SvgText
diff --git a/tests/test_main.py b/src/ewoksdraw/tests/test_main.py
similarity index 100%
rename from tests/test_main.py
rename to src/ewoksdraw/tests/test_main.py