eventsource-py 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- eventsource_py-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +29 -0
- eventsource_py-0.1.0/.github/workflows/ci.yml +162 -0
- eventsource_py-0.1.0/.github/workflows/docs.yml +145 -0
- eventsource_py-0.1.0/.github/workflows/release.yml +197 -0
- eventsource_py-0.1.0/.gitignore +96 -0
- eventsource_py-0.1.0/.pre-commit-config.yaml +36 -0
- eventsource_py-0.1.0/CHANGELOG.md +40 -0
- eventsource_py-0.1.0/LICENSE +21 -0
- eventsource_py-0.1.0/PKG-INFO +332 -0
- eventsource_py-0.1.0/README.md +274 -0
- eventsource_py-0.1.0/RELEASING.md +197 -0
- eventsource_py-0.1.0/docker-compose.test.yml +62 -0
- eventsource_py-0.1.0/docs/adrs/0000-template.md +129 -0
- eventsource_py-0.1.0/docs/adrs/0001-async-first-design.md +278 -0
- eventsource_py-0.1.0/docs/adrs/0002-pydantic-event-models.md +318 -0
- eventsource_py-0.1.0/docs/adrs/0003-optimistic-locking.md +292 -0
- eventsource_py-0.1.0/docs/adrs/0004-projection-error-handling.md +387 -0
- eventsource_py-0.1.0/docs/adrs/0005-api-design-patterns.md +341 -0
- eventsource_py-0.1.0/docs/adrs/0006-event-registry-serialization.md +393 -0
- eventsource_py-0.1.0/docs/adrs/index.md +103 -0
- eventsource_py-0.1.0/docs/api/aggregates.md +514 -0
- eventsource_py-0.1.0/docs/api/bus.md +540 -0
- eventsource_py-0.1.0/docs/api/events.md +331 -0
- eventsource_py-0.1.0/docs/api/index.md +580 -0
- eventsource_py-0.1.0/docs/api/projections.md +514 -0
- eventsource_py-0.1.0/docs/api/stores.md +660 -0
- eventsource_py-0.1.0/docs/architecture.md +382 -0
- eventsource_py-0.1.0/docs/development/code-structure.md +814 -0
- eventsource_py-0.1.0/docs/development/testing.md +1664 -0
- eventsource_py-0.1.0/docs/eventsource-py.code-workspace +14 -0
- eventsource_py-0.1.0/docs/examples/basic-order.md +285 -0
- eventsource_py-0.1.0/docs/examples/multi-tenant.md +941 -0
- eventsource_py-0.1.0/docs/examples/projections.md +682 -0
- eventsource_py-0.1.0/docs/examples/sqlite-usage.md +649 -0
- eventsource_py-0.1.0/docs/examples/testing.md +477 -0
- eventsource_py-0.1.0/docs/faq.md +784 -0
- eventsource_py-0.1.0/docs/getting-started.md +502 -0
- eventsource_py-0.1.0/docs/guides/authentication.md +1239 -0
- eventsource_py-0.1.0/docs/guides/error-handling.md +926 -0
- eventsource_py-0.1.0/docs/guides/multi-tenant.md +941 -0
- eventsource_py-0.1.0/docs/guides/production.md +1548 -0
- eventsource_py-0.1.0/docs/guides/sqlite-backend.md +460 -0
- eventsource_py-0.1.0/docs/index.md +152 -0
- eventsource_py-0.1.0/docs/infrastructure-tracking.md +140 -0
- eventsource_py-0.1.0/examples/__init__.py +8 -0
- eventsource_py-0.1.0/examples/aggregate_example.py +473 -0
- eventsource_py-0.1.0/examples/basic_usage.py +264 -0
- eventsource_py-0.1.0/examples/projection_example.py +511 -0
- eventsource_py-0.1.0/mkdocs.yml +95 -0
- eventsource_py-0.1.0/py.typed +0 -0
- eventsource_py-0.1.0/pyproject.toml +136 -0
- eventsource_py-0.1.0/scripts/validate_examples.py +287 -0
- eventsource_py-0.1.0/src/eventsource/__init__.py +231 -0
- eventsource_py-0.1.0/src/eventsource/aggregates/__init__.py +21 -0
- eventsource_py-0.1.0/src/eventsource/aggregates/base.py +443 -0
- eventsource_py-0.1.0/src/eventsource/aggregates/repository.py +294 -0
- eventsource_py-0.1.0/src/eventsource/bus/__init__.py +76 -0
- eventsource_py-0.1.0/src/eventsource/bus/interface.py +302 -0
- eventsource_py-0.1.0/src/eventsource/bus/memory.py +580 -0
- eventsource_py-0.1.0/src/eventsource/bus/redis.py +1487 -0
- eventsource_py-0.1.0/src/eventsource/config.py +7 -0
- eventsource_py-0.1.0/src/eventsource/events/__init__.py +33 -0
- eventsource_py-0.1.0/src/eventsource/events/base.py +281 -0
- eventsource_py-0.1.0/src/eventsource/events/registry.py +436 -0
- eventsource_py-0.1.0/src/eventsource/exceptions.py +112 -0
- eventsource_py-0.1.0/src/eventsource/migrations/SCHEMA_DESIGN.md +238 -0
- eventsource_py-0.1.0/src/eventsource/migrations/__init__.py +319 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/all.sql +170 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/checkpoints.sql +1 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/dlq.sql +1 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/events.sql +1 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/events_partitioned.sql +1 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/outbox.sql +1 -0
- eventsource_py-0.1.0/src/eventsource/migrations/schemas/sqlite_all.sql +154 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/all_tables.py.template +213 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/checkpoints.py.template +166 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/dlq.py.template +234 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/events.py.template +141 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/outbox.py.template +145 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/checkpoints.sql +165 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/dlq.sql +303 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/events.sql +113 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/events_partitioned.sql +238 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/outbox.sql +191 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/checkpoints.sql +65 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/dlq.sql +101 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/events.sql +103 -0
- eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/outbox.sql +97 -0
- eventsource_py-0.1.0/src/eventsource/projections/__init__.py +88 -0
- eventsource_py-0.1.0/src/eventsource/projections/base.py +799 -0
- eventsource_py-0.1.0/src/eventsource/projections/coordinator.py +542 -0
- eventsource_py-0.1.0/src/eventsource/projections/decorators.py +102 -0
- eventsource_py-0.1.0/src/eventsource/projections/protocols.py +161 -0
- eventsource_py-0.1.0/src/eventsource/py.typed +0 -0
- eventsource_py-0.1.0/src/eventsource/repositories/__init__.py +86 -0
- eventsource_py-0.1.0/src/eventsource/repositories/_connection.py +65 -0
- eventsource_py-0.1.0/src/eventsource/repositories/_json.py +84 -0
- eventsource_py-0.1.0/src/eventsource/repositories/checkpoint.py +717 -0
- eventsource_py-0.1.0/src/eventsource/repositories/dlq.py +1124 -0
- eventsource_py-0.1.0/src/eventsource/repositories/outbox.py +816 -0
- eventsource_py-0.1.0/src/eventsource/stores/__init__.py +45 -0
- eventsource_py-0.1.0/src/eventsource/stores/in_memory.py +573 -0
- eventsource_py-0.1.0/src/eventsource/stores/interface.py +696 -0
- eventsource_py-0.1.0/src/eventsource/stores/postgresql.py +919 -0
- eventsource_py-0.1.0/src/eventsource/stores/sqlite.py +978 -0
- eventsource_py-0.1.0/src/eventsource/types.py +23 -0
- eventsource_py-0.1.0/tests/__init__.py +1 -0
- eventsource_py-0.1.0/tests/conftest.py +248 -0
- eventsource_py-0.1.0/tests/fixtures/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/__init__.py +22 -0
- eventsource_py-0.1.0/tests/integration/bus/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/bus/test_redis.py +597 -0
- eventsource_py-0.1.0/tests/integration/conftest.py +774 -0
- eventsource_py-0.1.0/tests/integration/e2e/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/e2e/test_full_flow.py +548 -0
- eventsource_py-0.1.0/tests/integration/projections/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/projections/test_database_projection.py +586 -0
- eventsource_py-0.1.0/tests/integration/repositories/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/repositories/test_checkpoint.py +298 -0
- eventsource_py-0.1.0/tests/integration/repositories/test_dlq.py +460 -0
- eventsource_py-0.1.0/tests/integration/repositories/test_outbox.py +478 -0
- eventsource_py-0.1.0/tests/integration/stores/__init__.py +1 -0
- eventsource_py-0.1.0/tests/integration/stores/test_postgresql.py +895 -0
- eventsource_py-0.1.0/tests/repositories/__init__.py +1 -0
- eventsource_py-0.1.0/tests/repositories/test_sqlite_repos.py +954 -0
- eventsource_py-0.1.0/tests/stores/__init__.py +1 -0
- eventsource_py-0.1.0/tests/stores/test_sqlite_event_store.py +1214 -0
- eventsource_py-0.1.0/tests/unit/__init__.py +1 -0
- eventsource_py-0.1.0/tests/unit/test_additional_coverage.py +493 -0
- eventsource_py-0.1.0/tests/unit/test_aggregate_repository.py +1000 -0
- eventsource_py-0.1.0/tests/unit/test_aggregate_root.py +1349 -0
- eventsource_py-0.1.0/tests/unit/test_checkpoint_repository.py +682 -0
- eventsource_py-0.1.0/tests/unit/test_connection_helper.py +316 -0
- eventsource_py-0.1.0/tests/unit/test_dlq_repository.py +1148 -0
- eventsource_py-0.1.0/tests/unit/test_domain_event.py +854 -0
- eventsource_py-0.1.0/tests/unit/test_edge_cases.py +621 -0
- eventsource_py-0.1.0/tests/unit/test_event_bus.py +989 -0
- eventsource_py-0.1.0/tests/unit/test_event_registry.py +749 -0
- eventsource_py-0.1.0/tests/unit/test_event_store_interface.py +852 -0
- eventsource_py-0.1.0/tests/unit/test_exceptions.py +260 -0
- eventsource_py-0.1.0/tests/unit/test_in_memory_event_store.py +1157 -0
- eventsource_py-0.1.0/tests/unit/test_json_encoder.py +166 -0
- eventsource_py-0.1.0/tests/unit/test_outbox_repository.py +846 -0
- eventsource_py-0.1.0/tests/unit/test_postgresql_event_store.py +1248 -0
- eventsource_py-0.1.0/tests/unit/test_projection_base.py +1076 -0
- eventsource_py-0.1.0/tests/unit/test_projection_coordinator.py +666 -0
- eventsource_py-0.1.0/tests/unit/test_projection_decorators.py +229 -0
- eventsource_py-0.1.0/tests/unit/test_projection_protocols.py +236 -0
- eventsource_py-0.1.0/tests/unit/test_redis_event_bus.py +1132 -0
- eventsource_py-0.1.0/uv.lock +1660 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
description: Report a bug or unexpected behavior
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
|
|
9
|
+
A clear and concise description of the bug.
|
|
10
|
+
|
|
11
|
+
## Steps to Reproduce
|
|
12
|
+
|
|
13
|
+
1. Step one
|
|
14
|
+
2. Step two
|
|
15
|
+
3. ...
|
|
16
|
+
|
|
17
|
+
## Expected Behavior
|
|
18
|
+
|
|
19
|
+
What you expected to happen.
|
|
20
|
+
|
|
21
|
+
## Actual Behavior
|
|
22
|
+
|
|
23
|
+
What actually happened.
|
|
24
|
+
|
|
25
|
+
## Environment
|
|
26
|
+
|
|
27
|
+
- Python version: [e.g., 3.11.5]
|
|
28
|
+
- eventsource-client version: [e.g., 0.1.0]
|
|
29
|
+
- OS: [e.g., Ubuntu 22.04, macOS 14.0, Windows 11]
|
|
30
|
+
|
|
31
|
+
## Additional Context
|
|
32
|
+
|
|
33
|
+
Add any other context, stack traces, or screenshots.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Documentation
|
|
4
|
+
url: https://[ORGANIZATION].github.io/eventsource-py
|
|
5
|
+
about: Check our documentation for answers
|
|
6
|
+
- name: Questions & Discussions
|
|
7
|
+
url: https://github.com/[ORGANIZATION]/eventsource-py/discussions
|
|
8
|
+
about: Ask questions and discuss ideas
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
description: Suggest a new feature or enhancement
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Problem Statement
|
|
8
|
+
|
|
9
|
+
Describe the problem you're trying to solve or the limitation you've encountered.
|
|
10
|
+
|
|
11
|
+
## Proposed Solution
|
|
12
|
+
|
|
13
|
+
Describe the solution you'd like to see.
|
|
14
|
+
|
|
15
|
+
## Alternatives Considered
|
|
16
|
+
|
|
17
|
+
What alternatives have you considered?
|
|
18
|
+
|
|
19
|
+
## Additional Context
|
|
20
|
+
|
|
21
|
+
Add any other context, mockups, or examples.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Brief description of what this PR does.
|
|
4
|
+
|
|
5
|
+
## Type of Change
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fix (non-breaking change that fixes an issue)
|
|
8
|
+
- [ ] New feature (non-breaking change that adds functionality)
|
|
9
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
|
10
|
+
- [ ] Documentation update
|
|
11
|
+
- [ ] Refactoring (no functional changes)
|
|
12
|
+
- [ ] Tests only
|
|
13
|
+
|
|
14
|
+
## Checklist
|
|
15
|
+
|
|
16
|
+
- [ ] My code follows the project's code style
|
|
17
|
+
- [ ] I have added tests that prove my fix/feature works
|
|
18
|
+
- [ ] All new and existing tests pass
|
|
19
|
+
- [ ] I have updated the documentation (if applicable)
|
|
20
|
+
- [ ] I have updated the CHANGELOG.md
|
|
21
|
+
- [ ] I have added type hints to new code
|
|
22
|
+
|
|
23
|
+
## Related Issues
|
|
24
|
+
|
|
25
|
+
Closes #(issue number)
|
|
26
|
+
|
|
27
|
+
## Additional Notes
|
|
28
|
+
|
|
29
|
+
Any additional context for reviewers.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# CI Workflow
|
|
2
|
+
# Runs linting, type checking, and tests on push and pull requests
|
|
3
|
+
#
|
|
4
|
+
# Jobs:
|
|
5
|
+
# - lint: ruff check and format verification
|
|
6
|
+
# - type-check: mypy strict type checking
|
|
7
|
+
# - test: pytest with coverage (matrix: Python 3.11, 3.12)
|
|
8
|
+
|
|
9
|
+
name: CI
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
pull_request:
|
|
15
|
+
branches: [main]
|
|
16
|
+
workflow_call: # Allow release workflow to call this
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: ci-${{ github.ref }}
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
# Linting with ruff
|
|
27
|
+
lint:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- name: Checkout
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- name: Setup Python
|
|
34
|
+
uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: '3.11'
|
|
37
|
+
cache: 'pip'
|
|
38
|
+
cache-dependency-path: pyproject.toml
|
|
39
|
+
|
|
40
|
+
- name: Install dependencies
|
|
41
|
+
run: |
|
|
42
|
+
pip install --upgrade pip
|
|
43
|
+
pip install -e ".[dev]"
|
|
44
|
+
|
|
45
|
+
- name: Run ruff check
|
|
46
|
+
run: ruff check .
|
|
47
|
+
|
|
48
|
+
- name: Run ruff format check
|
|
49
|
+
run: ruff format --check .
|
|
50
|
+
|
|
51
|
+
# Type checking with mypy
|
|
52
|
+
type-check:
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- name: Checkout
|
|
56
|
+
uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Setup Python
|
|
59
|
+
uses: actions/setup-python@v5
|
|
60
|
+
with:
|
|
61
|
+
python-version: '3.11'
|
|
62
|
+
cache: 'pip'
|
|
63
|
+
cache-dependency-path: pyproject.toml
|
|
64
|
+
|
|
65
|
+
- name: Install dependencies
|
|
66
|
+
run: |
|
|
67
|
+
pip install --upgrade pip
|
|
68
|
+
pip install -e ".[dev,all]"
|
|
69
|
+
|
|
70
|
+
- name: Run mypy
|
|
71
|
+
run: mypy src/
|
|
72
|
+
|
|
73
|
+
# Testing with pytest
|
|
74
|
+
test:
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
strategy:
|
|
77
|
+
fail-fast: false
|
|
78
|
+
matrix:
|
|
79
|
+
python-version: ['3.11', '3.12']
|
|
80
|
+
|
|
81
|
+
steps:
|
|
82
|
+
- name: Checkout
|
|
83
|
+
uses: actions/checkout@v4
|
|
84
|
+
|
|
85
|
+
- name: Setup Python ${{ matrix.python-version }}
|
|
86
|
+
uses: actions/setup-python@v5
|
|
87
|
+
with:
|
|
88
|
+
python-version: ${{ matrix.python-version }}
|
|
89
|
+
cache: 'pip'
|
|
90
|
+
cache-dependency-path: pyproject.toml
|
|
91
|
+
|
|
92
|
+
- name: Install dependencies
|
|
93
|
+
run: |
|
|
94
|
+
pip install --upgrade pip
|
|
95
|
+
pip install -e ".[dev,all]"
|
|
96
|
+
|
|
97
|
+
- name: Run tests
|
|
98
|
+
run: |
|
|
99
|
+
pytest --cov=src/eventsource --cov-report=xml --cov-report=term-missing \
|
|
100
|
+
-m "not integration and not postgres and not redis and not e2e"
|
|
101
|
+
|
|
102
|
+
- name: Upload coverage report
|
|
103
|
+
if: matrix.python-version == '3.11'
|
|
104
|
+
uses: actions/upload-artifact@v4
|
|
105
|
+
with:
|
|
106
|
+
name: coverage-report
|
|
107
|
+
path: coverage.xml
|
|
108
|
+
retention-days: 7
|
|
109
|
+
|
|
110
|
+
# Integration tests (optional, requires services)
|
|
111
|
+
integration:
|
|
112
|
+
runs-on: ubuntu-latest
|
|
113
|
+
needs: [lint, type-check, test]
|
|
114
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
115
|
+
|
|
116
|
+
services:
|
|
117
|
+
postgres:
|
|
118
|
+
image: postgres:16
|
|
119
|
+
env:
|
|
120
|
+
POSTGRES_USER: test
|
|
121
|
+
POSTGRES_PASSWORD: test
|
|
122
|
+
POSTGRES_DB: eventsource_test
|
|
123
|
+
ports:
|
|
124
|
+
- 5432:5432
|
|
125
|
+
options: >-
|
|
126
|
+
--health-cmd pg_isready
|
|
127
|
+
--health-interval 10s
|
|
128
|
+
--health-timeout 5s
|
|
129
|
+
--health-retries 5
|
|
130
|
+
|
|
131
|
+
redis:
|
|
132
|
+
image: redis:7
|
|
133
|
+
ports:
|
|
134
|
+
- 6379:6379
|
|
135
|
+
options: >-
|
|
136
|
+
--health-cmd "redis-cli ping"
|
|
137
|
+
--health-interval 10s
|
|
138
|
+
--health-timeout 5s
|
|
139
|
+
--health-retries 5
|
|
140
|
+
|
|
141
|
+
steps:
|
|
142
|
+
- name: Checkout
|
|
143
|
+
uses: actions/checkout@v4
|
|
144
|
+
|
|
145
|
+
- name: Setup Python
|
|
146
|
+
uses: actions/setup-python@v5
|
|
147
|
+
with:
|
|
148
|
+
python-version: '3.11'
|
|
149
|
+
cache: 'pip'
|
|
150
|
+
cache-dependency-path: pyproject.toml
|
|
151
|
+
|
|
152
|
+
- name: Install dependencies
|
|
153
|
+
run: |
|
|
154
|
+
pip install --upgrade pip
|
|
155
|
+
pip install -e ".[dev,all]"
|
|
156
|
+
|
|
157
|
+
- name: Run integration tests
|
|
158
|
+
env:
|
|
159
|
+
DATABASE_URL: postgresql://test:test@localhost:5432/eventsource_test
|
|
160
|
+
REDIS_URL: redis://localhost:6379
|
|
161
|
+
run: |
|
|
162
|
+
pytest -m "integration or postgres or redis" --cov=src/eventsource --cov-report=term-missing
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Documentation CI/CD Workflow
|
|
2
|
+
# Builds, validates, and deploys documentation to GitHub Pages
|
|
3
|
+
#
|
|
4
|
+
# Triggers:
|
|
5
|
+
# - Push to main (docs paths) -> Build + Deploy
|
|
6
|
+
# - Pull requests (docs paths) -> Build only (no deploy)
|
|
7
|
+
# - Manual dispatch -> Build + Deploy (if on main)
|
|
8
|
+
|
|
9
|
+
name: Documentation
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
paths:
|
|
15
|
+
- 'docs/**'
|
|
16
|
+
- 'mkdocs.yml'
|
|
17
|
+
- 'src/**/*.py' # For API doc generation
|
|
18
|
+
- 'examples/**' # Example files
|
|
19
|
+
- 'scripts/validate_examples.py'
|
|
20
|
+
- '.github/workflows/docs.yml'
|
|
21
|
+
pull_request:
|
|
22
|
+
branches: [main]
|
|
23
|
+
paths:
|
|
24
|
+
- 'docs/**'
|
|
25
|
+
- 'mkdocs.yml'
|
|
26
|
+
- 'src/**/*.py'
|
|
27
|
+
- 'examples/**'
|
|
28
|
+
- 'scripts/validate_examples.py'
|
|
29
|
+
- '.github/workflows/docs.yml'
|
|
30
|
+
workflow_dispatch:
|
|
31
|
+
|
|
32
|
+
# Allow only one concurrent deployment, skip in-progress for PRs
|
|
33
|
+
concurrency:
|
|
34
|
+
group: pages-${{ github.ref }}
|
|
35
|
+
cancel-in-progress: true
|
|
36
|
+
|
|
37
|
+
# Sets permissions of the GITHUB_TOKEN for Pages deployment
|
|
38
|
+
permissions:
|
|
39
|
+
contents: read
|
|
40
|
+
|
|
41
|
+
jobs:
|
|
42
|
+
# Build documentation
|
|
43
|
+
build:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout
|
|
47
|
+
uses: actions/checkout@v4
|
|
48
|
+
with:
|
|
49
|
+
fetch-depth: 0 # Fetch all history for git-based plugins
|
|
50
|
+
|
|
51
|
+
- name: Setup Python
|
|
52
|
+
uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: '3.11'
|
|
55
|
+
cache: 'pip'
|
|
56
|
+
cache-dependency-path: pyproject.toml
|
|
57
|
+
|
|
58
|
+
- name: Install dependencies
|
|
59
|
+
run: |
|
|
60
|
+
pip install --upgrade pip
|
|
61
|
+
pip install -e ".[docs]"
|
|
62
|
+
|
|
63
|
+
- name: Build documentation
|
|
64
|
+
run: mkdocs build --strict
|
|
65
|
+
|
|
66
|
+
- name: Upload artifact for GitHub Pages
|
|
67
|
+
uses: actions/upload-pages-artifact@v3
|
|
68
|
+
with:
|
|
69
|
+
path: site/
|
|
70
|
+
|
|
71
|
+
- name: Upload artifact for PR review
|
|
72
|
+
if: github.event_name == 'pull_request'
|
|
73
|
+
uses: actions/upload-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
name: docs-preview
|
|
76
|
+
path: site/
|
|
77
|
+
retention-days: 7
|
|
78
|
+
|
|
79
|
+
# Validate code examples
|
|
80
|
+
validate-examples:
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
steps:
|
|
83
|
+
- name: Checkout
|
|
84
|
+
uses: actions/checkout@v4
|
|
85
|
+
|
|
86
|
+
- name: Setup Python
|
|
87
|
+
uses: actions/setup-python@v5
|
|
88
|
+
with:
|
|
89
|
+
python-version: '3.11'
|
|
90
|
+
cache: 'pip'
|
|
91
|
+
cache-dependency-path: pyproject.toml
|
|
92
|
+
|
|
93
|
+
- name: Install package
|
|
94
|
+
run: |
|
|
95
|
+
pip install --upgrade pip
|
|
96
|
+
pip install -e .
|
|
97
|
+
|
|
98
|
+
- name: Validate example syntax
|
|
99
|
+
run: python scripts/validate_examples.py --syntax
|
|
100
|
+
|
|
101
|
+
- name: Run examples
|
|
102
|
+
run: python scripts/validate_examples.py
|
|
103
|
+
|
|
104
|
+
# Check for broken links
|
|
105
|
+
link-check:
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- name: Checkout
|
|
109
|
+
uses: actions/checkout@v4
|
|
110
|
+
|
|
111
|
+
- name: Link Checker
|
|
112
|
+
uses: lycheeverse/lychee-action@v1
|
|
113
|
+
with:
|
|
114
|
+
args: >-
|
|
115
|
+
--verbose
|
|
116
|
+
--no-progress
|
|
117
|
+
--accept 200,204,206
|
|
118
|
+
--exclude-mail
|
|
119
|
+
--exclude-path './site'
|
|
120
|
+
--exclude 'your-org'
|
|
121
|
+
--exclude 'localhost'
|
|
122
|
+
--exclude '127.0.0.1'
|
|
123
|
+
'docs/**/*.md'
|
|
124
|
+
'README.md'
|
|
125
|
+
fail: true
|
|
126
|
+
|
|
127
|
+
# Deploy to GitHub Pages (only on push to main)
|
|
128
|
+
deploy:
|
|
129
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
130
|
+
needs: [build, link-check, validate-examples]
|
|
131
|
+
runs-on: ubuntu-latest
|
|
132
|
+
|
|
133
|
+
# Grant permissions for GitHub Pages deployment
|
|
134
|
+
permissions:
|
|
135
|
+
pages: write
|
|
136
|
+
id-token: write
|
|
137
|
+
|
|
138
|
+
environment:
|
|
139
|
+
name: github-pages
|
|
140
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
141
|
+
|
|
142
|
+
steps:
|
|
143
|
+
- name: Deploy to GitHub Pages
|
|
144
|
+
id: deployment
|
|
145
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Release Workflow
|
|
2
|
+
# Publishes package to PyPI when a version tag is pushed
|
|
3
|
+
#
|
|
4
|
+
# Triggers on tags matching v* (e.g., v0.1.0, v1.0.0a1)
|
|
5
|
+
# - Stable versions (v1.0.0) -> PyPI
|
|
6
|
+
# - Pre-releases (v1.0.0a1, v1.0.0b1) -> TestPyPI
|
|
7
|
+
# - Release candidates (v1.0.0rc1) -> PyPI (marked as pre-release)
|
|
8
|
+
|
|
9
|
+
name: Release
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- 'v*'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write # For GitHub Release creation
|
|
18
|
+
id-token: write # For Trusted Publishing (OIDC)
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
# Validate release tag and extract version info
|
|
22
|
+
validate:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
outputs:
|
|
25
|
+
version: ${{ steps.version.outputs.version }}
|
|
26
|
+
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
|
|
27
|
+
publish_target: ${{ steps.version.outputs.publish_target }}
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
|
|
32
|
+
- name: Extract version from tag
|
|
33
|
+
id: version
|
|
34
|
+
run: |
|
|
35
|
+
TAG=${GITHUB_REF#refs/tags/v}
|
|
36
|
+
echo "version=$TAG" >> $GITHUB_OUTPUT
|
|
37
|
+
|
|
38
|
+
# Determine if this is a pre-release and where to publish
|
|
39
|
+
if [[ "$TAG" =~ (a|b)[0-9]+ ]]; then
|
|
40
|
+
# Alpha or Beta -> TestPyPI
|
|
41
|
+
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
|
42
|
+
echo "publish_target=testpypi" >> $GITHUB_OUTPUT
|
|
43
|
+
elif [[ "$TAG" =~ rc[0-9]+ ]]; then
|
|
44
|
+
# Release candidate -> PyPI but marked as pre-release
|
|
45
|
+
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
|
46
|
+
echo "publish_target=pypi" >> $GITHUB_OUTPUT
|
|
47
|
+
else
|
|
48
|
+
# Stable release -> PyPI
|
|
49
|
+
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
|
50
|
+
echo "publish_target=pypi" >> $GITHUB_OUTPUT
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
- name: Setup Python
|
|
54
|
+
uses: actions/setup-python@v5
|
|
55
|
+
with:
|
|
56
|
+
python-version: '3.11'
|
|
57
|
+
|
|
58
|
+
- name: Validate version matches pyproject.toml
|
|
59
|
+
run: |
|
|
60
|
+
pip install tomli
|
|
61
|
+
PYPROJECT_VERSION=$(python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])")
|
|
62
|
+
if [[ "${{ steps.version.outputs.version }}" != "$PYPROJECT_VERSION" ]]; then
|
|
63
|
+
echo "::error::Tag version (${{ steps.version.outputs.version }}) does not match pyproject.toml ($PYPROJECT_VERSION)"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
echo "Version validated: $PYPROJECT_VERSION"
|
|
67
|
+
|
|
68
|
+
# Run CI checks (reuse existing workflow)
|
|
69
|
+
ci:
|
|
70
|
+
needs: validate
|
|
71
|
+
uses: ./.github/workflows/ci.yml
|
|
72
|
+
|
|
73
|
+
# Build distribution packages
|
|
74
|
+
build:
|
|
75
|
+
needs: ci
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
steps:
|
|
78
|
+
- name: Checkout
|
|
79
|
+
uses: actions/checkout@v4
|
|
80
|
+
|
|
81
|
+
- name: Setup Python
|
|
82
|
+
uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: '3.11'
|
|
85
|
+
|
|
86
|
+
- name: Install build tools
|
|
87
|
+
run: pip install build
|
|
88
|
+
|
|
89
|
+
- name: Build distributions
|
|
90
|
+
run: python -m build
|
|
91
|
+
|
|
92
|
+
- name: Upload artifacts
|
|
93
|
+
uses: actions/upload-artifact@v4
|
|
94
|
+
with:
|
|
95
|
+
name: dist
|
|
96
|
+
path: dist/
|
|
97
|
+
|
|
98
|
+
# Publish to PyPI (stable releases and RCs)
|
|
99
|
+
publish-pypi:
|
|
100
|
+
needs: [validate, build]
|
|
101
|
+
if: needs.validate.outputs.publish_target == 'pypi'
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
environment: pypi
|
|
104
|
+
steps:
|
|
105
|
+
- name: Download artifacts
|
|
106
|
+
uses: actions/download-artifact@v4
|
|
107
|
+
with:
|
|
108
|
+
name: dist
|
|
109
|
+
path: dist/
|
|
110
|
+
|
|
111
|
+
- name: Publish to PyPI
|
|
112
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
113
|
+
|
|
114
|
+
# Publish to TestPyPI (alpha and beta releases)
|
|
115
|
+
publish-testpypi:
|
|
116
|
+
needs: [validate, build]
|
|
117
|
+
if: needs.validate.outputs.publish_target == 'testpypi'
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
environment: testpypi
|
|
120
|
+
steps:
|
|
121
|
+
- name: Download artifacts
|
|
122
|
+
uses: actions/download-artifact@v4
|
|
123
|
+
with:
|
|
124
|
+
name: dist
|
|
125
|
+
path: dist/
|
|
126
|
+
|
|
127
|
+
- name: Publish to TestPyPI
|
|
128
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
129
|
+
with:
|
|
130
|
+
repository-url: https://test.pypi.org/legacy/
|
|
131
|
+
|
|
132
|
+
# Create GitHub Release
|
|
133
|
+
github-release:
|
|
134
|
+
needs: [validate, build, publish-pypi, publish-testpypi]
|
|
135
|
+
if: always() && needs.build.result == 'success' && (needs.publish-pypi.result == 'success' || needs.publish-testpypi.result == 'success' || needs.publish-pypi.result == 'skipped' || needs.publish-testpypi.result == 'skipped')
|
|
136
|
+
runs-on: ubuntu-latest
|
|
137
|
+
steps:
|
|
138
|
+
- name: Checkout
|
|
139
|
+
uses: actions/checkout@v4
|
|
140
|
+
|
|
141
|
+
- name: Download artifacts
|
|
142
|
+
uses: actions/download-artifact@v4
|
|
143
|
+
with:
|
|
144
|
+
name: dist
|
|
145
|
+
path: dist/
|
|
146
|
+
|
|
147
|
+
- name: Extract changelog for this version
|
|
148
|
+
id: changelog
|
|
149
|
+
run: |
|
|
150
|
+
VERSION=${{ needs.validate.outputs.version }}
|
|
151
|
+
# Extract the section for this version from CHANGELOG.md
|
|
152
|
+
# This captures everything between ## [VERSION] and the next ## [
|
|
153
|
+
CONTENT=$(awk "/^## \[$VERSION\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md)
|
|
154
|
+
|
|
155
|
+
# Handle multi-line content for GitHub Actions
|
|
156
|
+
echo "content<<EOF" >> $GITHUB_OUTPUT
|
|
157
|
+
echo "$CONTENT" >> $GITHUB_OUTPUT
|
|
158
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
159
|
+
|
|
160
|
+
- name: Create GitHub Release
|
|
161
|
+
uses: softprops/action-gh-release@v2
|
|
162
|
+
with:
|
|
163
|
+
files: dist/*
|
|
164
|
+
prerelease: ${{ needs.validate.outputs.is_prerelease }}
|
|
165
|
+
body: |
|
|
166
|
+
## What's Changed
|
|
167
|
+
|
|
168
|
+
${{ steps.changelog.outputs.content }}
|
|
169
|
+
|
|
170
|
+
## Installation
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pip install eventsource-py==${{ needs.validate.outputs.version }}
|
|
174
|
+
```
|
|
175
|
+
generate_release_notes: false
|
|
176
|
+
|
|
177
|
+
# Post-publish verification
|
|
178
|
+
verify:
|
|
179
|
+
needs: [validate, publish-pypi]
|
|
180
|
+
if: needs.publish-pypi.result == 'success'
|
|
181
|
+
runs-on: ubuntu-latest
|
|
182
|
+
steps:
|
|
183
|
+
- name: Wait for PyPI propagation
|
|
184
|
+
run: sleep 60
|
|
185
|
+
|
|
186
|
+
- name: Setup Python
|
|
187
|
+
uses: actions/setup-python@v5
|
|
188
|
+
with:
|
|
189
|
+
python-version: '3.11'
|
|
190
|
+
|
|
191
|
+
- name: Install from PyPI
|
|
192
|
+
run: pip install eventsource-py==${{ needs.validate.outputs.version }}
|
|
193
|
+
|
|
194
|
+
- name: Verify import and version
|
|
195
|
+
run: |
|
|
196
|
+
python -c "import eventsource; print(f'Installed version: {eventsource.__version__}')"
|
|
197
|
+
python -c "from eventsource import DomainEvent, InMemoryEventStore; print('Basic imports successful')"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
docs/futures/
|
|
2
|
+
docs/tasks/
|
|
3
|
+
|
|
4
|
+
# Byte-compiled / optimized / DLL files
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
|
|
9
|
+
# C extensions
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
*.manifest
|
|
32
|
+
*.spec
|
|
33
|
+
|
|
34
|
+
# Installer logs
|
|
35
|
+
pip-log.txt
|
|
36
|
+
pip-delete-this-directory.txt
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*.cover
|
|
48
|
+
*.py,cover
|
|
49
|
+
.hypothesis/
|
|
50
|
+
.pytest_cache/
|
|
51
|
+
|
|
52
|
+
# Translations
|
|
53
|
+
*.mo
|
|
54
|
+
*.pot
|
|
55
|
+
|
|
56
|
+
# Environments
|
|
57
|
+
.env
|
|
58
|
+
.venv
|
|
59
|
+
env/
|
|
60
|
+
venv/
|
|
61
|
+
ENV/
|
|
62
|
+
env.bak/
|
|
63
|
+
venv.bak/
|
|
64
|
+
|
|
65
|
+
# mypy
|
|
66
|
+
.mypy_cache/
|
|
67
|
+
.dmypy.json
|
|
68
|
+
dmypy.json
|
|
69
|
+
|
|
70
|
+
# ruff
|
|
71
|
+
.ruff_cache/
|
|
72
|
+
|
|
73
|
+
# IDEs
|
|
74
|
+
.idea/
|
|
75
|
+
.vscode/
|
|
76
|
+
*.swp
|
|
77
|
+
*.swo
|
|
78
|
+
*~
|
|
79
|
+
.project
|
|
80
|
+
.pydevproject
|
|
81
|
+
.settings/
|
|
82
|
+
|
|
83
|
+
# Jupyter Notebook
|
|
84
|
+
.ipynb_checkpoints
|
|
85
|
+
|
|
86
|
+
# Local development
|
|
87
|
+
*.local
|
|
88
|
+
.env.local
|
|
89
|
+
.env.*.local
|
|
90
|
+
|
|
91
|
+
# OS files
|
|
92
|
+
.DS_Store
|
|
93
|
+
Thumbs.db
|
|
94
|
+
|
|
95
|
+
# MkDocs documentation site
|
|
96
|
+
site/
|