Skip to content

Commit 9502c59

Browse files
committed
feat: initial FlowBoard implementation
Signed-off-by: Damian Skrzyński <polprog.tech@gmail.com>
1 parent 2cdee24 commit 9502c59

164 files changed

Lines changed: 42702 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
strategy:
16+
matrix:
17+
python-version: ["3.12", "3.13"]
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Set up Python ${{ matrix.python-version }}
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
27+
- name: Install dependencies
28+
run: pip install -e ".[dev]" httpx
29+
30+
- name: Lint with ruff
31+
run: ruff check src/ tests/
32+
33+
- name: Run tests
34+
run: pytest --cov=flowboard --cov-report=xml -v --junitxml=test-results.xml
35+
36+
- name: i18n coverage check
37+
run: python -c "
38+
import json, sys;
39+
en = set(json.load(open('src/flowboard/i18n/en.json')).keys());
40+
pl = set(json.load(open('src/flowboard/i18n/pl.json')).keys());
41+
missing = en - pl;
42+
[print(f'Missing in pl.json: {k}') for k in sorted(missing)];
43+
sys.exit(1) if missing else print('i18n: all keys present')
44+
"
45+
46+
- name: Generate demo dashboard
47+
run: flowboard demo --output output/demo.html
48+
49+
- name: Verify demo output exists
50+
run: test -f output/demo.html
51+
52+
- name: Upload test results
53+
uses: actions/upload-artifact@v4
54+
if: always()
55+
with:
56+
name: test-results-${{ matrix.python-version }}
57+
path: test-results.xml
58+
59+
docker:
60+
runs-on: ubuntu-latest
61+
needs: test
62+
if: github.ref == 'refs/heads/main'
63+
steps:
64+
- uses: actions/checkout@v4
65+
66+
- name: Build Docker image
67+
run: docker build -t flowboard:latest .
68+
69+
- name: Smoke test container
70+
run: |
71+
docker run -d --name fb-test -p 8084:8084 flowboard:latest serve --host 0.0.0.0 --port 8084
72+
sleep 5
73+
curl -sf http://localhost:8084/health/live || exit 1
74+
docker stop fb-test

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
__pycache__/
2+
*.py[cod]
3+
*$py.class
4+
*.so
5+
*.egg-info/
6+
dist/
7+
build/
8+
.eggs/
9+
*.egg
10+
.mypy_cache/
11+
.ruff_cache/
12+
.pytest_cache/
13+
htmlcov/
14+
.coverage
15+
.env
16+
*.env
17+
config.json
18+
!examples/config.example.json
19+
output/
20+
*.html
21+
!src/flowboard/presentation/html/templates/**/*.html
22+
.venv/
23+
venv/
24+
.idea/
25+
.vscode/
26+
*.swp
27+
*.swo
28+
*~
29+
.DS_Store

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog
2+
3+
## [1.0.0] - 2026-03-28
4+
5+
### Added
6+
7+
- Jira-based roadmap, delivery, and workload intelligence dashboard
8+
- Board snapshot analytics with dependency heatmaps
9+
- Multi-locale i18n support (EN, PL)
10+
- HTML report generation with Jinja2 templates
11+
- CLI interface via Typer
12+
- FastAPI-based web server with uvicorn
13+
- JSON Schema configuration validation
14+
- Docker and docker-compose deployment support

CONTRIBUTING.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Contributing to FlowBoard
2+
3+
Thank you for your interest in improving FlowBoard! This document provides guidelines for contributing.
4+
5+
## Development Setup
6+
7+
```bash
8+
git clone https://github.com/POLPROG-TECH/FlowBoard.git
9+
cd FlowBoard
10+
python3 -m venv .venv
11+
source .venv/bin/activate
12+
pip install -e ".[dev]"
13+
```
14+
15+
## Code Standards
16+
17+
- **Python 3.12+** with full type hints on all public APIs
18+
- **Ruff** for linting and formatting: `ruff check src/ tests/`
19+
- **mypy** for type checking: `mypy src/flowboard/`
20+
- **pytest** for testing: `pytest`
21+
22+
## Architecture
23+
24+
FlowBoard follows a clean layered architecture. See `docs/architecture.md` for details.
25+
26+
```
27+
src/flowboard/
28+
├── cli/ # Typer CLI (generate, validate, verify, demo, version)
29+
├── application/ # Orchestration pipeline, services
30+
├── domain/ # Models, analytics, risk, workload, overlap, dependencies,
31+
│ # timeline, scrum, simulation, pi
32+
├── infrastructure/ # Jira client/connector/normalizer, config loader/validator
33+
├── i18n/ # Translator engine, en.json, pl.json (927 keys)
34+
├── presentation/ # HTML renderer, Jinja2 templates, components, charts, export
35+
└── shared/ # Types, enums, utilities
36+
```
37+
38+
Key rules:
39+
- Domain layer has **zero** infrastructure imports
40+
- Presentation layer depends on domain, never on Jira client directly
41+
- Config is loaded once and passed down — no global singletons
42+
- All Jira API access goes through `infrastructure/jira/`
43+
44+
## Making Changes
45+
46+
1. Create a feature branch from `main`
47+
2. Write or update tests for your changes
48+
3. Ensure all tests pass: `pytest`
49+
4. Ensure linting passes: `ruff check src/ tests/`
50+
5. Submit a pull request with a clear description
51+
52+
## Test Guidelines
53+
54+
- Use **GIVEN / WHEN / THEN** style for behavior tests
55+
- Mock Jira API calls — never hit real Jira in tests
56+
- Focus on analytics correctness and edge cases
57+
- Keep tests fast and isolated
58+
59+
## Commit Messages
60+
61+
Use clear, descriptive commit messages:
62+
```
63+
feat: add burndown chart to sprint health view
64+
fix: correct story point aggregation for sub-tasks
65+
docs: update configuration guide for custom fields
66+
```
67+
68+
## Internationalization (i18n)
69+
70+
FlowBoard supports multiple languages. Currently supported locales: **English (en)** and **Polish (pl)**.
71+
72+
### Selecting a Language
73+
74+
Set the locale in your config file:
75+
```json
76+
{ "locale": "pl" }
77+
```
78+
79+
Or via CLI flag:
80+
```bash
81+
flowboard generate --config config.json --locale pl
82+
```
83+
84+
Or via environment variable:
85+
```bash
86+
export FLOWBOARD_LOCALE=pl
87+
```
88+
89+
**Precedence:** CLI flag > environment variable > config file > default (`en`).
90+
91+
### Translation Files
92+
93+
Translation files are JSON files in `src/flowboard/i18n/`:
94+
- `en.json` — English (reference/source)
95+
- `pl.json` — Polish
96+
97+
### Adding or Updating Translations
98+
99+
1. Add the new key to **both** `en.json` and `pl.json`.
100+
2. Use flat dot-notation keys (e.g. `"section.overview": "Overview"`).
101+
3. For interpolation, use `{variable}` placeholders: `"error.auth_failed": "Auth failed ({code})"`.
102+
4. For plurals, provide separate keys: `plural.day.one`, `plural.day.few`, `plural.day.many`, `plural.day.other`.
103+
5. Run `pytest tests/test_i18n.py` to verify key parity and placeholder consistency.
104+
105+
### Using Translations in Code
106+
107+
```python
108+
from flowboard.i18n.translator import Translator
109+
110+
t = Translator("pl")
111+
t("tab.overview") # "📋 Przegląd"
112+
t("cli.error", error="x") # "Błąd: x"
113+
t.plural(3, "plural.day.one", "plural.day.few", "plural.day.many") # "3 dni"
114+
t.format_date_short(date) # "18 mar"
115+
t.format_number(1234.5) # "1 234,5"
116+
```
117+
118+
### Adding a New Language
119+
120+
1. Copy `en.json` to `<code>.json` (e.g. `de.json`).
121+
2. Translate all values.
122+
3. Update `_meta.locale` to the new code.
123+
4. Add the locale code to the `"locale"` enum in `config.schema.json`.
124+
5. Add the locale code to the Pydantic config model's locale field.
125+
6. Add plural rules in `translator.py` if the language has complex pluralization.
126+
7. Run `pytest tests/test_i18n.py` to verify.
127+
128+
## Questions?
129+
130+
Open an issue or reach out to the FlowBoard team internally.

Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
FROM python:3.13-slim AS builder
2+
3+
WORKDIR /build
4+
COPY pyproject.toml README.md ./
5+
COPY src/ src/
6+
7+
RUN pip install --no-cache-dir --prefix=/install .
8+
9+
# ── Runtime stage ──────────────────────────────────────────────────
10+
FROM python:3.13-slim
11+
12+
LABEL maintainer="FlowBoard Team"
13+
LABEL org.opencontainers.image.title="FlowBoard"
14+
LABEL org.opencontainers.image.description="Jira-Based Delivery & Workload Intelligence Dashboard"
15+
16+
RUN groupadd -r flowboard && useradd -r -g flowboard -d /app flowboard
17+
18+
COPY --from=builder /install /usr/local
19+
COPY src/ /app/src/
20+
COPY examples/ /app/examples/
21+
COPY config.schema.json /app/
22+
23+
WORKDIR /app
24+
RUN mkdir -p /app/output && chown -R flowboard:flowboard /app
25+
26+
USER flowboard
27+
28+
ENV PYTHONPATH=/app/src \
29+
PYTHONUNBUFFERED=1 \
30+
FLOWBOARD_LOG_FORMAT=json \
31+
PORT=8084
32+
33+
EXPOSE 8084
34+
35+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
36+
CMD python -c "import os,urllib.request; urllib.request.urlopen(f'http://localhost:{os.environ.get(\"PORT\",\"8084\")}/health/live')" || exit 1
37+
38+
ENTRYPOINT ["flowboard"]
39+
CMD ["serve", "--host", "0.0.0.0", "--port", "8084"]

0 commit comments

Comments
 (0)