modwire 3.2.0__tar.gz → 4.0.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.
- modwire-4.0.0/.github/modwire-ecosystem.yml +169 -0
- modwire-4.0.0/.github/scripts/reconcile_ecosystem.py +400 -0
- modwire-4.0.0/.github/workflows/ci.yml +30 -0
- modwire-4.0.0/.github/workflows/python-github-release.yml +34 -0
- modwire-4.0.0/.github/workflows/python-package.yml +84 -0
- modwire-4.0.0/.github/workflows/python-release-build.yml +86 -0
- modwire-4.0.0/.github/workflows/release.yml +46 -0
- {modwire-3.2.0 → modwire-4.0.0}/.gitignore +1 -0
- modwire-4.0.0/.modwire/boundaries.yaml +44 -0
- modwire-4.0.0/.modwire/shape.yaml +5 -0
- modwire-4.0.0/CHANGELOG.md +88 -0
- {modwire-3.2.0 → modwire-4.0.0}/CONTRIBUTING.md +3 -1
- modwire-4.0.0/MANIFEST.in +1 -0
- modwire-4.0.0/Makefile +6 -0
- modwire-4.0.0/PKG-INFO +119 -0
- modwire-4.0.0/README.md +81 -0
- modwire-4.0.0/docs/governance/github-ecosystem.md +182 -0
- modwire-4.0.0/docs/governance/python-workflows.md +123 -0
- modwire-4.0.0/docs/wiki/Development-checks.md +25 -0
- modwire-4.0.0/docs/wiki/Home.md +27 -0
- {modwire-3.2.0 → modwire-4.0.0}/pyproject.toml +16 -18
- modwire-4.0.0/src/modwire/__init__.py +12 -0
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire/_version.py +3 -3
- modwire-4.0.0/src/modwire/architecture/__init__.py +10 -0
- modwire-4.0.0/src/modwire/architecture/app.py +137 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/__init__.py +8 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/analyzer.py +56 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/analyzers/__init__.py +1 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/analyzers/analyzer_base.py +41 -0
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire/architecture/boundaries/analyzers/backward.py +10 -6
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire/architecture/boundaries/analyzers/no_cycles.py +10 -9
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire/architecture/boundaries/analyzers/no_reentry.py +10 -9
- modwire-4.0.0/src/modwire/architecture/boundaries/base.py +54 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/collector.py +32 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/tags/__init__.py +9 -0
- modwire-4.0.0/src/modwire/architecture/boundaries/tags/matcher.py +135 -0
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire/architecture/boundaries/tags/tag_map.py +6 -3
- modwire-4.0.0/src/modwire/architecture/insights/__init__.py +8 -0
- modwire-4.0.0/src/modwire/architecture/insights/base.py +14 -0
- modwire-4.0.0/src/modwire/architecture/insights/collector.py +31 -0
- modwire-4.0.0/src/modwire/architecture/insights/reporters/__init__.py +7 -0
- modwire-4.0.0/src/modwire/architecture/insights/reporters/base.py +43 -0
- modwire-4.0.0/src/modwire/architecture/insights/reporters/callables.py +60 -0
- {modwire-3.2.0/src/modwire/architecture/insight/reports → modwire-4.0.0/src/modwire/architecture/insights/reporters}/clusters.py +21 -19
- {modwire-3.2.0/src/modwire/architecture/insight/reports → modwire-4.0.0/src/modwire/architecture/insights/reporters}/coherence.py +24 -15
- {modwire-3.2.0/src/modwire/architecture/insight/reports → modwire-4.0.0/src/modwire/architecture/insights/reporters}/exports.py +18 -22
- {modwire-3.2.0/src/modwire/architecture/insight/reports → modwire-4.0.0/src/modwire/architecture/insights/reporters}/hotspots.py +25 -20
- modwire-4.0.0/src/modwire/architecture/map/__init__.py +11 -0
- modwire-4.0.0/src/modwire/architecture/map/base.py +20 -0
- modwire-4.0.0/src/modwire/architecture/map/collector.py +40 -0
- modwire-4.0.0/src/modwire/architecture/map/loader.py +63 -0
- modwire-4.0.0/src/modwire/architecture/shape/__init__.py +8 -0
- modwire-4.0.0/src/modwire/architecture/shape/base.py +92 -0
- modwire-4.0.0/src/modwire/architecture/shape/collector.py +42 -0
- {modwire-3.2.0/src/modwire/architecture/shape/rules → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/abstract_class_resolver.py +22 -18
- {modwire-3.2.0/src/modwire/architecture/shape/rules → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/callable_resolver.py +31 -31
- {modwire-3.2.0/src/modwire/architecture/shape/rules → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/class_resolver.py +25 -22
- modwire-4.0.0/src/modwire/architecture/shape/resolvers/file_resolver.py +77 -0
- {modwire-3.2.0/src/modwire/architecture/shape/rules → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/import_resolver.py +19 -12
- modwire-4.0.0/src/modwire/architecture/shape/resolvers/property_resolver.py +92 -0
- {modwire-3.2.0/src/modwire/architecture/shape/rules → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/signature_resolver.py +28 -24
- modwire-4.0.0/src/modwire/architecture/shape/resolvers/symbol_resolver.py +33 -0
- modwire-4.0.0/src/modwire/code/__init__.py +10 -0
- modwire-4.0.0/src/modwire/code/package.py +48 -0
- modwire-4.0.0/src/modwire/code/reader.py +9 -0
- modwire-4.0.0/src/modwire/code/writer.py +27 -0
- modwire-4.0.0/src/modwire/facade.py +30 -0
- modwire-4.0.0/src/modwire/layers/__init__.py +11 -0
- modwire-4.0.0/src/modwire/layers/app.py +9 -0
- modwire-4.0.0/src/modwire/modules/__init__.py +4 -0
- modwire-4.0.0/src/modwire/modules/app.py +9 -0
- modwire-4.0.0/src/modwire/projects/__init__.py +43 -0
- modwire-4.0.0/src/modwire/projects/app.py +9 -0
- modwire-4.0.0/src/modwire/projects/ecosystem.py +267 -0
- modwire-4.0.0/src/modwire/shared/__init__.py +19 -0
- modwire-4.0.0/src/modwire/shared/base.py +76 -0
- modwire-4.0.0/src/modwire/shared/config/__init__.py +36 -0
- modwire-4.0.0/src/modwire/shared/config/architecture.py +67 -0
- modwire-4.0.0/src/modwire/shared/config/layers.py +30 -0
- modwire-4.0.0/src/modwire/shared/config/modules.py +18 -0
- modwire-4.0.0/src/modwire/shared/config/modwire.py +54 -0
- modwire-4.0.0/src/modwire/shared/config/projects.py +27 -0
- modwire-3.2.0/src/modwire/architecture/shape/config.py → modwire-4.0.0/src/modwire/shared/config/shape.py +8 -13
- modwire-4.0.0/src/modwire/shared/report/__init__.py +18 -0
- modwire-4.0.0/src/modwire/shared/report/base.py +105 -0
- modwire-4.0.0/src/modwire.egg-info/PKG-INFO +119 -0
- modwire-4.0.0/src/modwire.egg-info/SOURCES.txt +104 -0
- modwire-4.0.0/src/modwire.egg-info/requires.txt +11 -0
- modwire-4.0.0/src/modwire.egg-info/scm_file_list.json +101 -0
- modwire-4.0.0/src/modwire.egg-info/scm_version.json +8 -0
- modwire-4.0.0/tests/test_architecture.py +19 -0
- modwire-4.0.0/tests/test_ecosystem_contract.py +68 -0
- modwire-4.0.0/tests/test_models.py +60 -0
- {modwire-3.2.0 → modwire-4.0.0}/uv.lock +60 -291
- modwire-3.2.0/.github/workflows/ci.yml +0 -45
- modwire-3.2.0/.github/workflows/release.yml +0 -210
- modwire-3.2.0/CHANGELOG.md +0 -49
- modwire-3.2.0/PKG-INFO +0 -247
- modwire-3.2.0/README.md +0 -212
- modwire-3.2.0/docs/wiki/Development-checks.md +0 -18
- modwire-3.2.0/docs/wiki/Home.md +0 -25
- modwire-3.2.0/src/modwire/__init__.py +0 -6
- modwire-3.2.0/src/modwire/architecture/__init__.py +0 -26
- modwire-3.2.0/src/modwire/architecture/boundaries/analyzers/__init__.py +0 -0
- modwire-3.2.0/src/modwire/architecture/boundaries/base.py +0 -93
- modwire-3.2.0/src/modwire/architecture/boundaries/config.py +0 -43
- modwire-3.2.0/src/modwire/architecture/boundaries/map.py +0 -155
- modwire-3.2.0/src/modwire/architecture/boundaries/pipeline.py +0 -108
- modwire-3.2.0/src/modwire/architecture/boundaries/tags/__init__.py +0 -0
- modwire-3.2.0/src/modwire/architecture/boundaries/tags/matcher.py +0 -131
- modwire-3.2.0/src/modwire/architecture/config.py +0 -14
- modwire-3.2.0/src/modwire/architecture/insight/__init__.py +0 -0
- modwire-3.2.0/src/modwire/architecture/insight/base.py +0 -14
- modwire-3.2.0/src/modwire/architecture/insight/pipeline.py +0 -92
- modwire-3.2.0/src/modwire/architecture/insight/reports/__init__.py +0 -22
- modwire-3.2.0/src/modwire/architecture/insight/reports/callables.py +0 -54
- modwire-3.2.0/src/modwire/architecture/report.py +0 -102
- modwire-3.2.0/src/modwire/architecture/root.py +0 -18
- modwire-3.2.0/src/modwire/architecture/shape/__init__.py +0 -0
- modwire-3.2.0/src/modwire/architecture/shape/base.py +0 -52
- modwire-3.2.0/src/modwire/architecture/shape/pipeline.py +0 -95
- modwire-3.2.0/src/modwire/architecture/shape/rules/__init__.py +0 -20
- modwire-3.2.0/src/modwire/architecture/shape/rules/file_resolver.py +0 -57
- modwire-3.2.0/src/modwire/architecture/shape/rules/property_resolver.py +0 -81
- modwire-3.2.0/src/modwire/architecture/shape/rules/symbol_resolver.py +0 -34
- modwire-3.2.0/src/modwire/modules/__init__.py +0 -3
- modwire-3.2.0/src/modwire/modules/generate.py +0 -74
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/copier.yml +0 -48
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Application/Ports/{{ repository_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Application/UseCases/{{ use_case_name }}.php.jinja +0 -32
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Domain/Entities/{{ entity_name }}.php.jinja +0 -45
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Domain/Events/{{ event_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Domain/Exceptions/{{ entity_name }}ValidationException.php.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Infrastructure/Persistence/InMemory{{ repository_name }}.php.jinja +0 -24
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/php/src/Interface/Http/{{ controller_name }}.php.jinja +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/application/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/application/ports/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/application/ports/{{ repository_name | lower }}.py.jinja +0 -13
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/application/use_cases/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/application/use_cases/{{ use_case_name | lower }}.py.jinja +0 -22
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/entities/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/entities/{{ entity_name | lower }}.py.jinja +0 -35
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/events/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/events/{{ event_name | lower }}.py.jinja +0 -7
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/exceptions/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/domain/exceptions/{{ entity_name | lower }}validationerror.py.jinja +0 -2
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/infrastructure/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/infrastructure/persistence/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/infrastructure/persistence/inmemory{{ repository_name | lower }}.py.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/interface/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/interface/http/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/python/{{ module_name }}/interface/http/{{ controller_name | lower }}.py.jinja +0 -15
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/application/ports/{{ repository_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/application/use_cases/{{ use_case_name }}.ts.jinja +0 -19
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/domain/entities/{{ entity_name }}.ts.jinja +0 -31
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/domain/events/{{ event_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/domain/exceptions/{{ entity_name }}ValidationError.ts.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/infrastructure/persistence/InMemory{{ repository_name }}.ts.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/clean/template/typescript/{{ module_name }}/interface/http/{{ controller_name }}.ts.jinja +0 -10
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/copier.yml +0 -68
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Application/Ports/{{ repository_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Application/UseCases/{{ use_case_name }}.php.jinja +0 -35
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/Aggregates/{{ aggregate_name }}.php.jinja +0 -44
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/Entities/{{ entity_name }}.php.jinja +0 -16
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/Events/{{ event_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/Exceptions/{{ aggregate_name }}ValidationException.php.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/Services/{{ domain_service_name }}.php.jinja +0 -15
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Domain/ValueObjects/{{ value_object_name }}.php.jinja +0 -17
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Infrastructure/Persistence/InMemory{{ repository_name }}.php.jinja +0 -24
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/php/src/BoundedContexts/{{ context_class_name }}/{{ module_class_name }}/Interface/Http/{{ controller_name }}.php.jinja +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/application/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/application/ports/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/application/ports/{{ repository_name | lower }}.py.jinja +0 -13
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/application/use_cases/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/application/use_cases/{{ use_case_name | lower }}.py.jinja +0 -28
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/aggregates/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/aggregates/{{ aggregate_name | lower }}.py.jinja +0 -37
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/entities/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/entities/{{ entity_name | lower }}.py.jinja +0 -9
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/events/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/events/{{ event_name | lower }}.py.jinja +0 -7
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/exceptions/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/exceptions/{{ aggregate_name | lower }}validationerror.py.jinja +0 -2
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/services/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/services/{{ domain_service_name | lower }}.py.jinja +0 -8
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/value_objects/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/value_objects/{{ value_object_name | lower }}.py.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/infrastructure/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/infrastructure/persistence/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/infrastructure/persistence/inmemory{{ repository_name | lower }}.py.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/interface/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/interface/http/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/python/bounded_contexts/{{ context_name }}/{{ module_name }}/interface/http/{{ controller_name | lower }}.py.jinja +0 -17
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/application/ports/{{ repository_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/application/use_cases/{{ use_case_name }}.ts.jinja +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/aggregates/{{ aggregate_name }}.ts.jinja +0 -29
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/entities/{{ entity_name }}.ts.jinja +0 -8
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/events/{{ event_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/exceptions/{{ aggregate_name }}ValidationError.ts.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/services/{{ domain_service_name }}.ts.jinja +0 -7
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/domain/value_objects/{{ value_object_name }}.ts.jinja +0 -9
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/infrastructure/persistence/InMemory{{ repository_name }}.ts.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/ddd_context/template/typescript/bounded_contexts/{{ context_name }}/{{ module_name }}/interface/http/{{ controller_name }}.ts.jinja +0 -10
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/copier.yml +0 -43
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Adapters/Inbound/Amqp/{{ command_name }}Consumer.php.jinja +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Adapters/Inbound/Web/{{ controller_name }}.php.jinja +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Adapters/Inbound/{{ service_name }}.php.jinja +0 -25
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Adapters/Outbound/Client/{{ aggregate_name }}Client.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Adapters/Outbound/Persistence/InMemory{{ repository_name }}.php.jinja +0 -24
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Domain/Events/{{ aggregate_name }}Created.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Domain/Exceptions/{{ aggregate_name }}ValidationException.php.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Domain/Models/{{ aggregate_name }}.php.jinja +0 -45
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Ports/Inbound/{{ command_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Ports/Inbound/{{ service_name }}Port.php.jinja +0 -12
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/php/src/Ports/Outbound/{{ repository_name }}.php.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/amqp/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/amqp/{{ command_name | lower }}consumer.py.jinja +0 -17
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/web/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/web/{{ controller_name | lower }}.py.jinja +0 -13
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/inbound/{{ service_name | lower }}.py.jinja +0 -15
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/outbound/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/outbound/client/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/outbound/client/{{ aggregate_name | lower }}client.py.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/outbound/persistence/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/adapters/outbound/persistence/inmemory{{ repository_name | lower }}.py.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/events/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/events/{{ aggregate_name | lower }}created.py.jinja +0 -9
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/exceptions/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/exceptions/{{ aggregate_name | lower }}validationerror.py.jinja +0 -5
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/models/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/domain/models/{{ aggregate_name | lower }}.py.jinja +0 -37
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/inbound/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/inbound/{{ command_name | lower }}.py.jinja +0 -9
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/inbound/{{ service_name | lower }}.py.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/outbound/__init__.py.jinja +0 -3
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/python/{{ module_name }}/ports/outbound/{{ repository_name | lower }}.py.jinja +0 -13
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/adapters/inbound/amqp/{{ command_name }}Consumer.ts.jinja +0 -10
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/adapters/inbound/web/{{ controller_name }}.ts.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/adapters/inbound/{{ service_name }}.ts.jinja +0 -13
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/adapters/outbound/client/{{ aggregate_name }}Client.ts.jinja +0 -5
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/adapters/outbound/persistence/InMemory{{ repository_name }}.ts.jinja +0 -14
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/domain/events/{{ aggregate_name }}Created.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/domain/exceptions/{{ aggregate_name }}ValidationError.ts.jinja +0 -1
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/domain/models/{{ aggregate_name }}.ts.jinja +0 -31
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/ports/inbound/{{ command_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/ports/inbound/{{ service_name }}Port.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/hexagonal/template/typescript/{{ module_name }}/ports/outbound/{{ repository_name }}.ts.jinja +0 -6
- modwire-3.2.0/src/modwire/modules/scaffoldings/layered/copier.yml +0 -23
- modwire-3.2.0/src/modwire/modules/scaffoldings/layered/template/{{ module_name }}/application.py.jinja +0 -18
- modwire-3.2.0/src/modwire/modules/scaffoldings/layered/template/{{ module_name }}/domain.py.jinja +0 -12
- modwire-3.2.0/src/modwire/modules/scaffoldings/layered/template/{{ module_name }}/infrastructure.py.jinja +0 -11
- modwire-3.2.0/src/modwire/modules/scaffoldings/layered/template/{{ module_name }}/ui.py.jinja +0 -20
- modwire-3.2.0/src/modwire/projects/__init__.py +0 -13
- modwire-3.2.0/src/modwire/projects/_operations.py +0 -287
- modwire-3.2.0/src/modwire/projects/generate.py +0 -126
- modwire-3.2.0/src/modwire/projects/profile.py +0 -321
- modwire-3.2.0/src/modwire/projects/root.py +0 -70
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/copier.yml +0 -33
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/.gitignore.jinja +0 -5
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/.modwire/project.json.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/README.md.jinja +0 -6
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/bin/console.jinja +0 -6
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/composer.json.jinja +0 -29
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/config/routes.yaml.jinja +0 -3
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/src/Infrastructure/Clients/Generated/.gitkeep.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/src/Kernel.php.jinja +0 -13
- modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/tests/KernelTest.php.jinja +0 -16
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/copier.yml +0 -90
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/.gitignore.jinja +0 -10
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/.modwire/project.json.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/README.md.jinja +0 -25
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/openapi/.gitkeep.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/pyproject.toml.jinja +0 -38
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/cli.py.jinja +0 -15
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/infrastructure/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/infrastructure/clients/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/infrastructure/clients/generated/.gitkeep.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/interface/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/interface/http/__init__.py.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/interface/http/router.py.jinja +0 -8
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/main.py.jinja +0 -14
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/src/{{ package_name }}/settings.py.jinja +0 -7
- modwire-3.2.0/src/modwire/projects/scaffoldings/python-fastapi-ddd-uv/template/tests/test_health.py.jinja +0 -12
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/copier.yml +0 -33
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/.gitignore.jinja +0 -5
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/.modwire/project.json.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/README.md.jinja +0 -6
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/nest-cli.json.jinja +0 -4
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/openapi/.gitkeep.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/package.json.jinja +0 -22
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/src/app.module.ts.jinja +0 -4
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/src/infrastructure/clients/generated/.gitkeep.jinja +0 -1
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/src/main.ts.jinja +0 -10
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/test/app.spec.ts.jinja +0 -7
- modwire-3.2.0/src/modwire/projects/scaffoldings/typescript-nestjs-ddd-pnpm/template/tsconfig.json.jinja +0 -12
- modwire-3.2.0/src/modwire.egg-info/PKG-INFO +0 -247
- modwire-3.2.0/src/modwire.egg-info/SOURCES.txt +0 -251
- modwire-3.2.0/src/modwire.egg-info/requires.txt +0 -9
- modwire-3.2.0/tests/architecture/boundaries/test_map.py +0 -69
- modwire-3.2.0/tests/architecture/boundaries/test_pipeline.py +0 -122
- modwire-3.2.0/tests/architecture/test_report.py +0 -110
- modwire-3.2.0/tests/modules/test_generate.py +0 -210
- modwire-3.2.0/tests/projects/test_project_generate.py +0 -225
- modwire-3.2.0/tests/projects/test_project_operations.py +0 -156
- {modwire-3.2.0 → modwire-4.0.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/LICENSE +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/docs/wiki/Reporting-bugs.md +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/docs/wiki/Requesting-features.md +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/setup.cfg +0 -0
- {modwire-3.2.0/src/modwire/architecture/boundaries → modwire-4.0.0/src/modwire/architecture/shape/resolvers}/__init__.py +0 -0
- /modwire-3.2.0/src/modwire/projects/scaffoldings/php-symfony-ddd-composer/template/openapi/.gitkeep.jinja → /modwire-4.0.0/src/modwire/py.typed +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire.egg-info/dependency_links.txt +0 -0
- {modwire-3.2.0 → modwire-4.0.0}/src/modwire.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
packages:
|
|
4
|
+
core:
|
|
5
|
+
repository: 9orky/modwire
|
|
6
|
+
distribution: modwire
|
|
7
|
+
component: Core
|
|
8
|
+
role: coordinator
|
|
9
|
+
lifecycle: active
|
|
10
|
+
summary: Typed coordination library and ecosystem integration gate.
|
|
11
|
+
depends_on: [extraction, mermaid, siren]
|
|
12
|
+
cli:
|
|
13
|
+
repository: 9orky/modwire-cli
|
|
14
|
+
distribution: modwire-cli
|
|
15
|
+
component: CLI
|
|
16
|
+
role: runtime
|
|
17
|
+
lifecycle: active
|
|
18
|
+
summary: Command-line runtime and user-facing workflows.
|
|
19
|
+
depends_on: [core]
|
|
20
|
+
extraction:
|
|
21
|
+
repository: 9orky/modwire-extraction
|
|
22
|
+
distribution: modwire-extraction
|
|
23
|
+
component: Extraction
|
|
24
|
+
role: building_block
|
|
25
|
+
lifecycle: active
|
|
26
|
+
summary: Canonical source extraction and normalization.
|
|
27
|
+
mermaid:
|
|
28
|
+
repository: 9orky/modwire-mermaid
|
|
29
|
+
distribution: modwire-mermaid
|
|
30
|
+
component: Mermaid
|
|
31
|
+
role: building_block
|
|
32
|
+
lifecycle: active
|
|
33
|
+
summary: Typed, deterministic Mermaid source generation.
|
|
34
|
+
siren:
|
|
35
|
+
repository: 9orky/modwire-siren
|
|
36
|
+
distribution: modwire-siren
|
|
37
|
+
component: Siren
|
|
38
|
+
role: building_block
|
|
39
|
+
lifecycle: active
|
|
40
|
+
summary: Typed Siren hypermedia and OpenAPI integration.
|
|
41
|
+
mcp:
|
|
42
|
+
repository: 9orky/modwire-mcp
|
|
43
|
+
distribution: modwire-mcp
|
|
44
|
+
component: MCP
|
|
45
|
+
role: integration
|
|
46
|
+
lifecycle: incubating
|
|
47
|
+
summary: MCP surface and future home of scaffolding operations.
|
|
48
|
+
depends_on: [core]
|
|
49
|
+
|
|
50
|
+
project:
|
|
51
|
+
owner: 9orky
|
|
52
|
+
title: Modwire Ecosystem
|
|
53
|
+
number: 4
|
|
54
|
+
visibility: public
|
|
55
|
+
default_package: core
|
|
56
|
+
description: Cross-repository roadmap and release coordination for the Modwire ecosystem.
|
|
57
|
+
governance_url: https://github.com/9orky/modwire/blob/main/docs/governance/github-ecosystem.md
|
|
58
|
+
|
|
59
|
+
workflows:
|
|
60
|
+
contract_ref: workflows-v1
|
|
61
|
+
ci_entrypoint: .github/workflows/ci.yml
|
|
62
|
+
release_entrypoint: .github/workflows/release.yml
|
|
63
|
+
verify_reusable: .github/workflows/python-package.yml
|
|
64
|
+
release_build_reusable: .github/workflows/python-release-build.yml
|
|
65
|
+
github_release_reusable: .github/workflows/python-github-release.yml
|
|
66
|
+
release_tag_pattern: ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$
|
|
67
|
+
artifact_name: python-package-distributions
|
|
68
|
+
pypi_environment: pypi
|
|
69
|
+
actions:
|
|
70
|
+
checkout: actions/checkout@v6
|
|
71
|
+
setup_python: actions/setup-python@v6
|
|
72
|
+
upload_artifact: actions/upload-artifact@v7
|
|
73
|
+
download_artifact: actions/download-artifact@v8
|
|
74
|
+
publish_pypi: pypa/gh-action-pypi-publish@release/v1
|
|
75
|
+
|
|
76
|
+
fields:
|
|
77
|
+
Status:
|
|
78
|
+
type: single_select
|
|
79
|
+
options: [Inbox, Ready, In progress, Blocked, Review, Done]
|
|
80
|
+
Horizon:
|
|
81
|
+
type: single_select
|
|
82
|
+
options: [Now, Next, Later]
|
|
83
|
+
Priority:
|
|
84
|
+
type: single_select
|
|
85
|
+
options: [P0, P1, P2, P3]
|
|
86
|
+
Component:
|
|
87
|
+
type: single_select
|
|
88
|
+
source: packages
|
|
89
|
+
Release train:
|
|
90
|
+
type: text
|
|
91
|
+
Target date:
|
|
92
|
+
type: date
|
|
93
|
+
Risk:
|
|
94
|
+
type: single_select
|
|
95
|
+
options: [Low, Medium, High]
|
|
96
|
+
|
|
97
|
+
views:
|
|
98
|
+
- name: Roadmap
|
|
99
|
+
layout: roadmap
|
|
100
|
+
group_by: Release train
|
|
101
|
+
slice_by: Component
|
|
102
|
+
- name: Now
|
|
103
|
+
layout: board
|
|
104
|
+
filter: "Horizon:Now -Status:Done"
|
|
105
|
+
group_by: Status
|
|
106
|
+
- name: By package
|
|
107
|
+
layout: table
|
|
108
|
+
filter: "-Status:Done"
|
|
109
|
+
group_by: Repository
|
|
110
|
+
- name: Blocked
|
|
111
|
+
layout: table
|
|
112
|
+
filter: "Status:Blocked"
|
|
113
|
+
group_by: Component
|
|
114
|
+
- name: Release readiness
|
|
115
|
+
layout: table
|
|
116
|
+
filter: "has:\"Release train\" -Status:Done"
|
|
117
|
+
group_by: Release train
|
|
118
|
+
- name: Inbox
|
|
119
|
+
layout: table
|
|
120
|
+
filter: "Status:Inbox"
|
|
121
|
+
|
|
122
|
+
labels:
|
|
123
|
+
"type:bug":
|
|
124
|
+
color: "d73a4a"
|
|
125
|
+
description: Incorrect existing behavior
|
|
126
|
+
"type:feature":
|
|
127
|
+
color: "0e8a16"
|
|
128
|
+
description: New user-facing capability
|
|
129
|
+
"type:maintenance":
|
|
130
|
+
color: "c5def5"
|
|
131
|
+
description: Internal maintenance
|
|
132
|
+
"type:docs":
|
|
133
|
+
color: "0075ca"
|
|
134
|
+
description: Documentation
|
|
135
|
+
ecosystem:
|
|
136
|
+
color: "5319e7"
|
|
137
|
+
description: Cross-package coordination
|
|
138
|
+
contract:
|
|
139
|
+
color: "1d76db"
|
|
140
|
+
description: Public contract or compatibility work
|
|
141
|
+
breaking:
|
|
142
|
+
color: "b60205"
|
|
143
|
+
description: Backward-incompatible change
|
|
144
|
+
blocked:
|
|
145
|
+
color: "e99695"
|
|
146
|
+
description: Blocked by another decision or delivery
|
|
147
|
+
release-gate:
|
|
148
|
+
color: "fbca04"
|
|
149
|
+
description: Must complete before a release
|
|
150
|
+
|
|
151
|
+
automation:
|
|
152
|
+
auto_add_filter: "is:open"
|
|
153
|
+
added_status: Inbox
|
|
154
|
+
closed_status: Done
|
|
155
|
+
merged_status: Done
|
|
156
|
+
archive_filter: "Status:Done updated:<@today-30d"
|
|
157
|
+
|
|
158
|
+
milestones:
|
|
159
|
+
scope: repository
|
|
160
|
+
naming: "<version-or-phase>: <outcome>"
|
|
161
|
+
close_when_complete: true
|
|
162
|
+
ecosystem_coordination_field: Release train
|
|
163
|
+
cross_repository_work: parent_issue_in_modwire_with_sub_issues
|
|
164
|
+
|
|
165
|
+
cadence:
|
|
166
|
+
triage: weekly
|
|
167
|
+
roadmap_review: monthly
|
|
168
|
+
release_readiness: before_each_package_release
|
|
169
|
+
project_status_update: monthly
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
import subprocess
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from modwire.projects import EcosystemContract, EcosystemDrift, ProjectFieldType
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
ROOT = Path(__file__).resolve().parents[2]
|
|
15
|
+
DEFAULT_CONTRACT = ROOT / ".github" / "modwire-ecosystem.yml"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def gh(*arguments: str) -> str:
|
|
19
|
+
result = subprocess.run(
|
|
20
|
+
["gh", *arguments],
|
|
21
|
+
check=True,
|
|
22
|
+
capture_output=True,
|
|
23
|
+
text=True,
|
|
24
|
+
)
|
|
25
|
+
return result.stdout
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def gh_json(*arguments: str) -> Any:
|
|
29
|
+
return json.loads(gh(*arguments))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def load_contract(path: Path) -> EcosystemContract:
|
|
33
|
+
return EcosystemContract.load_yaml(path)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def workflow_drift(contract: EcosystemContract) -> list[str]:
|
|
37
|
+
errors: list[str] = []
|
|
38
|
+
workflow_paths = (
|
|
39
|
+
contract.workflows.ci_entrypoint,
|
|
40
|
+
contract.workflows.release_entrypoint,
|
|
41
|
+
contract.workflows.verify_reusable,
|
|
42
|
+
contract.workflows.release_build_reusable,
|
|
43
|
+
contract.workflows.github_release_reusable,
|
|
44
|
+
)
|
|
45
|
+
contents: dict[str, str] = {}
|
|
46
|
+
for relative_path in workflow_paths:
|
|
47
|
+
path = ROOT / relative_path
|
|
48
|
+
if not path.is_file():
|
|
49
|
+
errors.append(f"missing workflow file {relative_path}")
|
|
50
|
+
continue
|
|
51
|
+
contents[relative_path] = path.read_text(encoding="utf-8")
|
|
52
|
+
|
|
53
|
+
expected_actions = {
|
|
54
|
+
"actions/checkout": contract.workflows.actions.checkout,
|
|
55
|
+
"actions/setup-python": contract.workflows.actions.setup_python,
|
|
56
|
+
"actions/upload-artifact": contract.workflows.actions.upload_artifact,
|
|
57
|
+
"actions/download-artifact": contract.workflows.actions.download_artifact,
|
|
58
|
+
"pypa/gh-action-pypi-publish": contract.workflows.actions.publish_pypi,
|
|
59
|
+
}
|
|
60
|
+
for path in sorted((ROOT / ".github" / "workflows").glob("*.yml")):
|
|
61
|
+
text = path.read_text(encoding="utf-8")
|
|
62
|
+
for action in re.findall(
|
|
63
|
+
r"(?:actions/(?:checkout|setup-python|upload-artifact|download-artifact)|"
|
|
64
|
+
r"pypa/gh-action-pypi-publish)@[^\s]+",
|
|
65
|
+
text,
|
|
66
|
+
):
|
|
67
|
+
name = action.split("@", maxsplit=1)[0]
|
|
68
|
+
if action != expected_actions[name]:
|
|
69
|
+
errors.append(f"{path.name}: unmanaged action reference {action}")
|
|
70
|
+
|
|
71
|
+
release = contents.get(contract.workflows.release_entrypoint, "")
|
|
72
|
+
release_build = contents.get(contract.workflows.release_build_reusable, "")
|
|
73
|
+
verify = contents.get(contract.workflows.verify_reusable, "")
|
|
74
|
+
required_references = {
|
|
75
|
+
contract.workflows.release_entrypoint: (
|
|
76
|
+
contract.workflows.release_build_reusable,
|
|
77
|
+
contract.workflows.github_release_reusable,
|
|
78
|
+
contract.workflows.actions.download_artifact,
|
|
79
|
+
contract.workflows.actions.publish_pypi,
|
|
80
|
+
),
|
|
81
|
+
contract.workflows.release_build_reusable: (
|
|
82
|
+
contract.workflows.actions.checkout,
|
|
83
|
+
contract.workflows.actions.setup_python,
|
|
84
|
+
contract.workflows.actions.upload_artifact,
|
|
85
|
+
),
|
|
86
|
+
contract.workflows.verify_reusable: (
|
|
87
|
+
contract.workflows.actions.checkout,
|
|
88
|
+
contract.workflows.actions.setup_python,
|
|
89
|
+
contract.workflows.actions.upload_artifact,
|
|
90
|
+
),
|
|
91
|
+
contract.workflows.github_release_reusable: (
|
|
92
|
+
contract.workflows.actions.download_artifact,
|
|
93
|
+
),
|
|
94
|
+
}
|
|
95
|
+
for path, references in required_references.items():
|
|
96
|
+
text = contents.get(path, "")
|
|
97
|
+
for reference in references:
|
|
98
|
+
if reference not in text:
|
|
99
|
+
errors.append(f"{path}: missing required reference {reference}")
|
|
100
|
+
|
|
101
|
+
for forbidden in (
|
|
102
|
+
"python - <<",
|
|
103
|
+
"SETUPTOOLS_SCM_PRETEND_VERSION",
|
|
104
|
+
"softprops/",
|
|
105
|
+
"types: [published]",
|
|
106
|
+
):
|
|
107
|
+
if forbidden in release or forbidden in release_build:
|
|
108
|
+
errors.append(f"release workflows contain forbidden pattern {forbidden}")
|
|
109
|
+
if contract.workflows.artifact_name not in release or contract.workflows.artifact_name not in release_build:
|
|
110
|
+
errors.append("release artifact name differs from the workflow contract")
|
|
111
|
+
github_release = contents.get(contract.workflows.github_release_reusable, "")
|
|
112
|
+
if (
|
|
113
|
+
"workflow_call:" not in verify
|
|
114
|
+
or "workflow_call:" not in release_build
|
|
115
|
+
or "workflow_call:" not in github_release
|
|
116
|
+
):
|
|
117
|
+
errors.append("reusable workflows must use workflow_call")
|
|
118
|
+
return errors
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def project_fields(contract: EcosystemContract) -> dict[str, dict[str, Any]]:
|
|
122
|
+
query = """
|
|
123
|
+
query($id: ID!) {
|
|
124
|
+
node(id: $id) {
|
|
125
|
+
... on ProjectV2 {
|
|
126
|
+
fields(first: 100) {
|
|
127
|
+
nodes {
|
|
128
|
+
__typename
|
|
129
|
+
... on ProjectV2Field { id name dataType }
|
|
130
|
+
... on ProjectV2SingleSelectField { id name options { name } }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
"""
|
|
137
|
+
project = gh_json(
|
|
138
|
+
"project",
|
|
139
|
+
"view",
|
|
140
|
+
str(contract.project.number),
|
|
141
|
+
"--owner",
|
|
142
|
+
contract.project.owner,
|
|
143
|
+
"--format",
|
|
144
|
+
"json",
|
|
145
|
+
)
|
|
146
|
+
data = gh_json(
|
|
147
|
+
"api",
|
|
148
|
+
"graphql",
|
|
149
|
+
"-F",
|
|
150
|
+
f"id={project['id']}",
|
|
151
|
+
"-f",
|
|
152
|
+
f"query={query}",
|
|
153
|
+
)
|
|
154
|
+
nodes = data["data"]["node"]["fields"]["nodes"]
|
|
155
|
+
return {node["name"]: node for node in nodes if node.get("name")}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def linked_repositories(contract: EcosystemContract) -> set[str]:
|
|
159
|
+
query = """
|
|
160
|
+
query($id: ID!) {
|
|
161
|
+
node(id: $id) {
|
|
162
|
+
... on ProjectV2 { repositories(first: 100) { nodes { nameWithOwner } } }
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
"""
|
|
166
|
+
project = gh_json(
|
|
167
|
+
"project",
|
|
168
|
+
"view",
|
|
169
|
+
str(contract.project.number),
|
|
170
|
+
"--owner",
|
|
171
|
+
contract.project.owner,
|
|
172
|
+
"--format",
|
|
173
|
+
"json",
|
|
174
|
+
)
|
|
175
|
+
data = gh_json(
|
|
176
|
+
"api",
|
|
177
|
+
"graphql",
|
|
178
|
+
"-F",
|
|
179
|
+
f"id={project['id']}",
|
|
180
|
+
"-f",
|
|
181
|
+
f"query={query}",
|
|
182
|
+
)
|
|
183
|
+
nodes = data["data"]["node"]["repositories"]["nodes"]
|
|
184
|
+
return {node["nameWithOwner"] for node in nodes}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def open_work_urls(contract: EcosystemContract) -> set[str]:
|
|
188
|
+
urls: set[str] = set()
|
|
189
|
+
for repository in contract.repositories():
|
|
190
|
+
for kind in ("issue", "pr"):
|
|
191
|
+
items = gh_json(
|
|
192
|
+
kind,
|
|
193
|
+
"list",
|
|
194
|
+
"--repo",
|
|
195
|
+
repository,
|
|
196
|
+
"--state",
|
|
197
|
+
"open",
|
|
198
|
+
"--limit",
|
|
199
|
+
"100",
|
|
200
|
+
"--json",
|
|
201
|
+
"url",
|
|
202
|
+
)
|
|
203
|
+
urls.update(item["url"] for item in items)
|
|
204
|
+
return urls
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def project_item_urls(contract: EcosystemContract) -> set[str]:
|
|
208
|
+
data = gh_json(
|
|
209
|
+
"project",
|
|
210
|
+
"item-list",
|
|
211
|
+
str(contract.project.number),
|
|
212
|
+
"--owner",
|
|
213
|
+
contract.project.owner,
|
|
214
|
+
"--limit",
|
|
215
|
+
"1000",
|
|
216
|
+
"--format",
|
|
217
|
+
"json",
|
|
218
|
+
)
|
|
219
|
+
return {
|
|
220
|
+
item["content"]["url"]
|
|
221
|
+
for item in data["items"]
|
|
222
|
+
if item.get("content", {}).get("url")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def label_drift(contract: EcosystemContract) -> list[str]:
|
|
227
|
+
errors: list[str] = []
|
|
228
|
+
for repository in contract.repositories():
|
|
229
|
+
actual = {
|
|
230
|
+
label["name"]: label
|
|
231
|
+
for label in gh_json(
|
|
232
|
+
"label",
|
|
233
|
+
"list",
|
|
234
|
+
"--repo",
|
|
235
|
+
repository,
|
|
236
|
+
"--limit",
|
|
237
|
+
"100",
|
|
238
|
+
"--json",
|
|
239
|
+
"name,color,description",
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
for name, expected in contract.labels.items():
|
|
243
|
+
label = actual.get(name)
|
|
244
|
+
if label is None:
|
|
245
|
+
errors.append(f"{repository}: missing label {name}")
|
|
246
|
+
continue
|
|
247
|
+
if label["color"].lower() != expected.color:
|
|
248
|
+
errors.append(f"{repository}: label {name} has the wrong color")
|
|
249
|
+
if label["description"] != expected.description:
|
|
250
|
+
errors.append(f"{repository}: label {name} has the wrong description")
|
|
251
|
+
return errors
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def inspect_live(contract: EcosystemContract) -> EcosystemDrift:
|
|
255
|
+
errors = workflow_drift(contract)
|
|
256
|
+
project = gh_json(
|
|
257
|
+
"project",
|
|
258
|
+
"view",
|
|
259
|
+
str(contract.project.number),
|
|
260
|
+
"--owner",
|
|
261
|
+
contract.project.owner,
|
|
262
|
+
"--format",
|
|
263
|
+
"json",
|
|
264
|
+
)
|
|
265
|
+
expected_project = {
|
|
266
|
+
"title": contract.project.title,
|
|
267
|
+
"public": contract.project.visibility.value == "public",
|
|
268
|
+
"shortDescription": contract.project.description,
|
|
269
|
+
"readme": contract.project_readme(),
|
|
270
|
+
}
|
|
271
|
+
for name, expected in expected_project.items():
|
|
272
|
+
if project[name] != expected:
|
|
273
|
+
errors.append(f"project {name} differs from the contract")
|
|
274
|
+
|
|
275
|
+
expected_repositories = set(contract.repositories())
|
|
276
|
+
actual_repositories = linked_repositories(contract)
|
|
277
|
+
for repository in sorted(expected_repositories - actual_repositories):
|
|
278
|
+
errors.append(f"project is not linked to {repository}")
|
|
279
|
+
for repository in sorted(actual_repositories - expected_repositories):
|
|
280
|
+
errors.append(f"project has unmanaged repository {repository}")
|
|
281
|
+
|
|
282
|
+
actual_fields = project_fields(contract)
|
|
283
|
+
for name, expected in contract.fields.items():
|
|
284
|
+
actual = actual_fields.get(name)
|
|
285
|
+
if actual is None:
|
|
286
|
+
errors.append(f"project is missing field {name}")
|
|
287
|
+
continue
|
|
288
|
+
if expected.type is ProjectFieldType.SINGLE_SELECT:
|
|
289
|
+
options = tuple(option["name"] for option in actual.get("options", ()))
|
|
290
|
+
if options != contract.field_options(name):
|
|
291
|
+
errors.append(f"project field {name} options differ from the contract")
|
|
292
|
+
elif actual.get("dataType", "").lower() != expected.type.value:
|
|
293
|
+
errors.append(f"project field {name} type differs from the contract")
|
|
294
|
+
|
|
295
|
+
missing_items = open_work_urls(contract) - project_item_urls(contract)
|
|
296
|
+
for url in sorted(missing_items):
|
|
297
|
+
errors.append(f"project is missing open work item {url}")
|
|
298
|
+
errors.extend(label_drift(contract))
|
|
299
|
+
return EcosystemDrift(
|
|
300
|
+
errors=tuple(errors),
|
|
301
|
+
manual_controls=(
|
|
302
|
+
"Saved Project views must be compared in the GitHub UI.",
|
|
303
|
+
"Project auto-add, close, merge, and archive workflows must be compared in the GitHub UI.",
|
|
304
|
+
),
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def apply_live(contract: EcosystemContract) -> None:
|
|
309
|
+
gh(
|
|
310
|
+
"project",
|
|
311
|
+
"edit",
|
|
312
|
+
str(contract.project.number),
|
|
313
|
+
"--owner",
|
|
314
|
+
contract.project.owner,
|
|
315
|
+
"--title",
|
|
316
|
+
contract.project.title,
|
|
317
|
+
"--visibility",
|
|
318
|
+
contract.project.visibility.value.upper(),
|
|
319
|
+
"--description",
|
|
320
|
+
contract.project.description,
|
|
321
|
+
"--readme",
|
|
322
|
+
contract.project_readme(),
|
|
323
|
+
)
|
|
324
|
+
linked = linked_repositories(contract)
|
|
325
|
+
for repository in contract.repositories():
|
|
326
|
+
if repository not in linked:
|
|
327
|
+
gh(
|
|
328
|
+
"project",
|
|
329
|
+
"link",
|
|
330
|
+
str(contract.project.number),
|
|
331
|
+
"--owner",
|
|
332
|
+
contract.project.owner,
|
|
333
|
+
"--repo",
|
|
334
|
+
repository,
|
|
335
|
+
)
|
|
336
|
+
for name, label in contract.labels.items():
|
|
337
|
+
gh(
|
|
338
|
+
"label",
|
|
339
|
+
"create",
|
|
340
|
+
name,
|
|
341
|
+
"--repo",
|
|
342
|
+
repository,
|
|
343
|
+
"--color",
|
|
344
|
+
label.color,
|
|
345
|
+
"--description",
|
|
346
|
+
label.description,
|
|
347
|
+
"--force",
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
existing_items = project_item_urls(contract)
|
|
351
|
+
for url in sorted(open_work_urls(contract) - existing_items):
|
|
352
|
+
gh(
|
|
353
|
+
"project",
|
|
354
|
+
"item-add",
|
|
355
|
+
str(contract.project.number),
|
|
356
|
+
"--owner",
|
|
357
|
+
contract.project.owner,
|
|
358
|
+
"--url",
|
|
359
|
+
url,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def parser() -> argparse.ArgumentParser:
|
|
364
|
+
result = argparse.ArgumentParser(description="Validate and reconcile Modwire governance")
|
|
365
|
+
result.add_argument(
|
|
366
|
+
"command",
|
|
367
|
+
choices=("validate", "check-live", "apply-live", "schema"),
|
|
368
|
+
nargs="?",
|
|
369
|
+
default="validate",
|
|
370
|
+
)
|
|
371
|
+
result.add_argument("--contract", type=Path, default=DEFAULT_CONTRACT)
|
|
372
|
+
return result
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def main() -> int:
|
|
376
|
+
arguments = parser().parse_args()
|
|
377
|
+
contract = load_contract(arguments.contract)
|
|
378
|
+
if arguments.command == "schema":
|
|
379
|
+
print(json.dumps(EcosystemContract.model_json_schema(), indent=2))
|
|
380
|
+
return 0
|
|
381
|
+
if arguments.command == "validate":
|
|
382
|
+
errors = workflow_drift(contract)
|
|
383
|
+
if errors:
|
|
384
|
+
print(EcosystemDrift(errors=tuple(errors)).pretty())
|
|
385
|
+
return 1
|
|
386
|
+
print(
|
|
387
|
+
f"valid ecosystem contract: {len(contract.packages)} packages, "
|
|
388
|
+
f"{len(contract.fields)} project fields"
|
|
389
|
+
)
|
|
390
|
+
return 0
|
|
391
|
+
if arguments.command == "apply-live":
|
|
392
|
+
apply_live(contract)
|
|
393
|
+
|
|
394
|
+
drift = inspect_live(contract)
|
|
395
|
+
print(drift.pretty())
|
|
396
|
+
return 0 if drift.is_clean() else 1
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
if __name__ == "__main__":
|
|
400
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
ecosystem-contract:
|
|
15
|
+
name: Ecosystem contract
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v6
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
- name: Install coordinator
|
|
25
|
+
run: python -m pip install -e .
|
|
26
|
+
- name: Validate ecosystem contract
|
|
27
|
+
run: python .github/scripts/reconcile_ecosystem.py validate
|
|
28
|
+
|
|
29
|
+
verify:
|
|
30
|
+
uses: ./.github/workflows/python-package.yml
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Reusable Python GitHub release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
release-tag:
|
|
7
|
+
description: Existing release tag used to create the GitHub Release.
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
artifact-name:
|
|
11
|
+
description: Name of the verified distribution artifact.
|
|
12
|
+
required: false
|
|
13
|
+
type: string
|
|
14
|
+
default: python-package-distributions
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
publish:
|
|
21
|
+
name: Create GitHub release
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Download release distributions
|
|
25
|
+
uses: actions/download-artifact@v8
|
|
26
|
+
with:
|
|
27
|
+
name: ${{ inputs.artifact-name }}
|
|
28
|
+
path: dist/
|
|
29
|
+
|
|
30
|
+
- name: Create GitHub release
|
|
31
|
+
env:
|
|
32
|
+
GH_TOKEN: ${{ github.token }}
|
|
33
|
+
RELEASE_TAG: ${{ inputs.release-tag }}
|
|
34
|
+
run: gh release create "$RELEASE_TAG" dist/* --verify-tag --generate-notes
|