django-due 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.
Potentially problematic release.
This version of django-due might be problematic. Click here for more details.
- django_due-0.1.0/.github/dependabot.yml +8 -0
- django_due-0.1.0/.github/pull_request_template.md +9 -0
- django_due-0.1.0/.github/workflows/ci.yml +132 -0
- django_due-0.1.0/.github/workflows/pr-title.yml +32 -0
- django_due-0.1.0/.github/workflows/release.yaml +224 -0
- django_due-0.1.0/.gitignore +15 -0
- django_due-0.1.0/.pre-commit-config.yaml +20 -0
- django_due-0.1.0/.python-version +1 -0
- django_due-0.1.0/.release-please-manifest.json +1 -0
- django_due-0.1.0/CHANGELOG.md +99 -0
- django_due-0.1.0/CONTRIBUTING.md +75 -0
- django_due-0.1.0/LICENSE +202 -0
- django_due-0.1.0/NOTICE +5 -0
- django_due-0.1.0/PKG-INFO +291 -0
- django_due-0.1.0/README.md +260 -0
- django_due-0.1.0/RELEASING.md +102 -0
- django_due-0.1.0/compose.yaml +23 -0
- django_due-0.1.0/docs/alternatives.md +128 -0
- django_due-0.1.0/docs/architecture.md +165 -0
- django_due-0.1.0/docs/backend-adoption.md +134 -0
- django_due-0.1.0/docs/capabilities.md +96 -0
- django_due-0.1.0/docs/completion-leases.md +51 -0
- django_due-0.1.0/docs/conformance-api.md +233 -0
- django_due-0.1.0/docs/conformance.md +480 -0
- django_due-0.1.0/docs/cutover-audit.md +182 -0
- django_due-0.1.0/docs/demo-comparisons.md +73 -0
- django_due-0.1.0/docs/extraction.md +47 -0
- django_due-0.1.0/docs/integration.md +206 -0
- django_due-0.1.0/docs/investigations/backend-migration-audit-2026-10-11.md +380 -0
- django_due-0.1.0/docs/migrations/arq.md +311 -0
- django_due-0.1.0/docs/migrations/celery.md +369 -0
- django_due-0.1.0/docs/migrations/chancy.md +310 -0
- django_due-0.1.0/docs/migrations/dbos.md +334 -0
- django_due-0.1.0/docs/migrations/django-q2.md +299 -0
- django_due-0.1.0/docs/migrations/django-rq.md +303 -0
- django_due-0.1.0/docs/migrations/django-tasks-db.md +353 -0
- django_due-0.1.0/docs/migrations/django-tasks-rq.md +352 -0
- django_due-0.1.0/docs/migrations/django-tasks.md +459 -0
- django_due-0.1.0/docs/migrations/dramatiq.md +299 -0
- django_due-0.1.0/docs/migrations/huey.md +347 -0
- django_due-0.1.0/docs/migrations/pgmq.md +310 -0
- django_due-0.1.0/docs/migrations/pgqueuer.md +312 -0
- django_due-0.1.0/docs/migrations/procrastinate.md +387 -0
- django_due-0.1.0/docs/migrations/rq.md +374 -0
- django_due-0.1.0/docs/migrations/taskiq.md +307 -0
- django_due-0.1.0/docs/migrations/temporal.md +339 -0
- django_due-0.1.0/docs/migrations.md +58 -0
- django_due-0.1.0/docs/operations.md +130 -0
- django_due-0.1.0/docs/recovery-walkthrough.md +121 -0
- django_due-0.1.0/docs/verification.md +105 -0
- django_due-0.1.0/docs/why-due.md +210 -0
- django_due-0.1.0/docs/work-in-progress/tickets/adopter-integration-third-audit-test-plan.md +16 -0
- django_due-0.1.0/docs/work-in-progress/tickets/application-outcome-proofs-test-plan.md +12 -0
- django_due-0.1.0/docs/work-in-progress/tickets/audit-port-and-guides-test-plan.md +47 -0
- django_due-0.1.0/docs/work-in-progress/tickets/backend-replacement-test-plan.md +20 -0
- django_due-0.1.0/docs/work-in-progress/tickets/be-harness-parity-test-plan.md +20 -0
- django_due-0.1.0/docs/work-in-progress/tickets/books-convergence-test-plan.md +3 -0
- django_due-0.1.0/docs/work-in-progress/tickets/codex-due-bindings-test-plan.md +33 -0
- django_due-0.1.0/docs/work-in-progress/tickets/codex-due-comparison-test-plan.md +46 -0
- django_due-0.1.0/docs/work-in-progress/tickets/codex-initial-extraction-test-plan.md +12 -0
- django_due-0.1.0/docs/work-in-progress/tickets/codex-scheduled-publication-test-plan.md +49 -0
- django_due-0.1.0/docs/work-in-progress/tickets/proof-resource-ownership-test-plan.md +26 -0
- django_due-0.1.0/docs/work-in-progress/tickets/selection-completeness-parity-test-plan.md +23 -0
- django_due-0.1.0/docs/work-in-progress/tickets/upstream-cutover-test-plan.md +55 -0
- django_due-0.1.0/examples/README.md +82 -0
- django_due-0.1.0/examples/__init__.py +5 -0
- django_due-0.1.0/examples/apps.py +11 -0
- django_due-0.1.0/examples/books/README.md +246 -0
- django_due-0.1.0/examples/books/__init__.py +0 -0
- django_due-0.1.0/examples/books/effects.py +43 -0
- django_due-0.1.0/examples/books/migrations/0001_initial.py +259 -0
- django_due-0.1.0/examples/books/migrations/__init__.py +0 -0
- django_due-0.1.0/examples/books/models.py +37 -0
- django_due-0.1.0/examples/books/search.py +73 -0
- django_due-0.1.0/examples/books/services.py +28 -0
- django_due-0.1.0/examples/books/templates/books/form.html +9 -0
- django_due-0.1.0/examples/books/templates/books/list.html +25 -0
- django_due-0.1.0/examples/books/views.py +30 -0
- django_due-0.1.0/examples/catalog/README.md +38 -0
- django_due-0.1.0/examples/catalog/__init__.py +0 -0
- django_due-0.1.0/examples/catalog/effects.py +33 -0
- django_due-0.1.0/examples/catalog/migrations/0001_initial.py +147 -0
- django_due-0.1.0/examples/catalog/migrations/__init__.py +0 -0
- django_due-0.1.0/examples/catalog/models.py +25 -0
- django_due-0.1.0/examples/catalog/services.py +23 -0
- django_due-0.1.0/examples/celery_app.py +13 -0
- django_due-0.1.0/examples/celery_migration/README.md +127 -0
- django_due-0.1.0/examples/celery_migration/__init__.py +1 -0
- django_due-0.1.0/examples/celery_migration/tasks.py +37 -0
- django_due-0.1.0/examples/comparison/README.md +79 -0
- django_due-0.1.0/examples/comparison/__init__.py +0 -0
- django_due-0.1.0/examples/comparison/settings.py +6 -0
- django_due-0.1.0/examples/comparison/tasks.py +51 -0
- django_due-0.1.0/examples/documents/README.md +28 -0
- django_due-0.1.0/examples/documents/__init__.py +0 -0
- django_due-0.1.0/examples/documents/apps.py +6 -0
- django_due-0.1.0/examples/documents/effects.py +43 -0
- django_due-0.1.0/examples/documents/migrations/0001_initial.py +142 -0
- django_due-0.1.0/examples/documents/migrations/0002_document_publication_failed.py +17 -0
- django_due-0.1.0/examples/documents/migrations/__init__.py +0 -0
- django_due-0.1.0/examples/documents/models.py +20 -0
- django_due-0.1.0/examples/documents/storage.py +53 -0
- django_due-0.1.0/examples/management/__init__.py +0 -0
- django_due-0.1.0/examples/management/commands/__init__.py +0 -0
- django_due-0.1.0/examples/management/commands/catalog_entry.py +20 -0
- django_due-0.1.0/examples/management/commands/print_book.py +16 -0
- django_due-0.1.0/examples/management/commands/scheduled_publication.py +53 -0
- django_due-0.1.0/examples/orders/README.md +47 -0
- django_due-0.1.0/examples/orders/__init__.py +0 -0
- django_due-0.1.0/examples/orders/effects.py +41 -0
- django_due-0.1.0/examples/orders/migrations/0001_initial.py +172 -0
- django_due-0.1.0/examples/orders/migrations/__init__.py +0 -0
- django_due-0.1.0/examples/orders/models.py +30 -0
- django_due-0.1.0/examples/orders/provider.py +63 -0
- django_due-0.1.0/examples/orders/services.py +13 -0
- django_due-0.1.0/examples/registry.py +17 -0
- django_due-0.1.0/examples/scheduled/README.md +250 -0
- django_due-0.1.0/examples/scheduled/__init__.py +1 -0
- django_due-0.1.0/examples/scheduled/effects.py +40 -0
- django_due-0.1.0/examples/scheduled/forms.py +16 -0
- django_due-0.1.0/examples/scheduled/migrations/0001_initial.py +158 -0
- django_due-0.1.0/examples/scheduled/migrations/0002_submission_identity.py +41 -0
- django_due-0.1.0/examples/scheduled/migrations/__init__.py +0 -0
- django_due-0.1.0/examples/scheduled/models.py +31 -0
- django_due-0.1.0/examples/scheduled/services.py +77 -0
- django_due-0.1.0/examples/scheduled/templates/scheduled/detail.html +13 -0
- django_due-0.1.0/examples/scheduled/templates/scheduled/list.html +10 -0
- django_due-0.1.0/examples/scheduled/views.py +88 -0
- django_due-0.1.0/examples/settings.py +35 -0
- django_due-0.1.0/examples/urls.py +11 -0
- django_due-0.1.0/pyproject.toml +96 -0
- django_due-0.1.0/release-please-config.json +62 -0
- django_due-0.1.0/scripts/check_adoption_report.py +111 -0
- django_due-0.1.0/scripts/check_backend_compatibility.py +103 -0
- django_due-0.1.0/scripts/check_wheel.py +44 -0
- django_due-0.1.0/src/due/__init__.py +1 -0
- django_due-0.1.0/src/due/_installed.py +58 -0
- django_due-0.1.0/src/due/_suite_inventory.py +119 -0
- django_due-0.1.0/src/due/django/__init__.py +4 -0
- django_due-0.1.0/src/due/django/apps.py +8 -0
- django_due-0.1.0/src/due/django/capabilities/__init__.py +4 -0
- django_due-0.1.0/src/due/django/capabilities/_attempt_recovery.py +45 -0
- django_due-0.1.0/src/due/django/capabilities/authoring.py +1074 -0
- django_due-0.1.0/src/due/django/capabilities/compensation.py +153 -0
- django_due-0.1.0/src/due/django/capabilities/observed_operations.py +133 -0
- django_due-0.1.0/src/due/django/capabilities/operations.py +393 -0
- django_due-0.1.0/src/due/django/capabilities/projection.py +237 -0
- django_due-0.1.0/src/due/django/capabilities/scheduled.py +288 -0
- django_due-0.1.0/src/due/django/completion.py +144 -0
- django_due-0.1.0/src/due/django/conformance/__init__.py +21 -0
- django_due-0.1.0/src/due/django/conformance/_binding.py +4 -0
- django_due-0.1.0/src/due/django/conformance/_internal/__init__.py +1 -0
- django_due-0.1.0/src/due/django/conformance/_internal/immutable_inputs.py +293 -0
- django_due-0.1.0/src/due/django/conformance/_internal/suite.py +1477 -0
- django_due-0.1.0/src/due/django/conformance/background.py +550 -0
- django_due-0.1.0/src/due/django/conformance/background_beat.py +60 -0
- django_due-0.1.0/src/due/django/conformance/binding.py +4 -0
- django_due-0.1.0/src/due/django/conformance/bindings.py +355 -0
- django_due-0.1.0/src/due/django/conformance/collected_effects.py +109 -0
- django_due-0.1.0/src/due/django/conformance/composition.py +257 -0
- django_due-0.1.0/src/due/django/conformance/concurrency.py +124 -0
- django_due-0.1.0/src/due/django/conformance/database.py +23 -0
- django_due-0.1.0/src/due/django/conformance/delivery.py +150 -0
- django_due-0.1.0/src/due/django/conformance/discovery_admissibility.py +189 -0
- django_due-0.1.0/src/due/django/conformance/enrollment.py +49 -0
- django_due-0.1.0/src/due/django/conformance/examples.py +215 -0
- django_due-0.1.0/src/due/django/conformance/host.py +35 -0
- django_due-0.1.0/src/due/django/conformance/indexes.py +81 -0
- django_due-0.1.0/src/due/django/conformance/interleavings.py +114 -0
- django_due-0.1.0/src/due/django/conformance/observations.py +251 -0
- django_due-0.1.0/src/due/django/conformance/provider.py +110 -0
- django_due-0.1.0/src/due/django/conformance/recovery_isolation.py +309 -0
- django_due-0.1.0/src/due/django/conformance/registrations.py +51 -0
- django_due-0.1.0/src/due/django/conformance/reporting.py +145 -0
- django_due-0.1.0/src/due/django/conformance/scenarios.py +581 -0
- django_due-0.1.0/src/due/django/conformance/seams.py +425 -0
- django_due-0.1.0/src/due/django/conformance/suite.py +97 -0
- django_due-0.1.0/src/due/django/conformance/suite_collection.py +238 -0
- django_due-0.1.0/src/due/django/conformance/worker_connection.py +16 -0
- django_due-0.1.0/src/due/django/declarations/__init__.py +4 -0
- django_due-0.1.0/src/due/django/declarations/capture.py +70 -0
- django_due-0.1.0/src/due/django/declarations/dependents.py +23 -0
- django_due-0.1.0/src/due/django/declarations/eligibility.py +48 -0
- django_due-0.1.0/src/due/django/declarations/external_services.py +56 -0
- django_due-0.1.0/src/due/django/declarations/mirrors.py +80 -0
- django_due-0.1.0/src/due/django/evidence/__init__.py +4 -0
- django_due-0.1.0/src/due/django/evidence/attempts.py +280 -0
- django_due-0.1.0/src/due/django/evidence/effect_evidence.py +101 -0
- django_due-0.1.0/src/due/django/integration.py +72 -0
- django_due-0.1.0/src/due/django/management/__init__.py +0 -0
- django_due-0.1.0/src/due/django/management/commands/__init__.py +0 -0
- django_due-0.1.0/src/due/django/management/commands/due_check.py +47 -0
- django_due-0.1.0/src/due/django/management/commands/due_status.py +96 -0
- django_due-0.1.0/src/due/django/migrations/0001_initial.py +102 -0
- django_due-0.1.0/src/due/django/migrations/__init__.py +1 -0
- django_due-0.1.0/src/due/django/models.py +329 -0
- django_due-0.1.0/src/due/django/public.py +113 -0
- django_due-0.1.0/src/due/django/runtime/__init__.py +4 -0
- django_due-0.1.0/src/due/django/runtime/_delivery.py +163 -0
- django_due-0.1.0/src/due/django/runtime/coordination.py +1133 -0
- django_due-0.1.0/src/due/django/runtime/counters.py +22 -0
- django_due-0.1.0/src/due/django/runtime/diagnostics.py +67 -0
- django_due-0.1.0/src/due/django/runtime/limits.py +7 -0
- django_due-0.1.0/src/due/django/runtime/metrics.py +297 -0
- django_due-0.1.0/src/due/django/runtime/names.py +13 -0
- django_due-0.1.0/src/due/django/runtime/recovery_pass.py +546 -0
- django_due-0.1.0/src/due/django/runtime/registry.py +204 -0
- django_due-0.1.0/src/due/django/runtime/tasks.py +59 -0
- django_due-0.1.0/src/due/django/runtime/transport.py +56 -0
- django_due-0.1.0/src/due/django/testing.py +136 -0
- django_due-0.1.0/src/due/errors.py +77 -0
- django_due-0.1.0/src/due/observability.py +17 -0
- django_due-0.1.0/src/due/observations.py +20 -0
- django_due-0.1.0/src/due/py.typed +0 -0
- django_due-0.1.0/src/due/pytest_plugin.py +69 -0
- django_due-0.1.0/src/due/retry_delays.py +33 -0
- django_due-0.1.0/tests/__init__.py +6 -0
- django_due-0.1.0/tests/capabilities/__init__.py +1 -0
- django_due-0.1.0/tests/capabilities/test_authoring.py +356 -0
- django_due-0.1.0/tests/capabilities/test_authoring_nonblocking.py +47 -0
- django_due-0.1.0/tests/capabilities/test_capability_round_trip_budget.py +199 -0
- django_due-0.1.0/tests/capabilities/test_compensation.py +116 -0
- django_due-0.1.0/tests/capabilities/test_continuations.py +142 -0
- django_due-0.1.0/tests/capabilities/test_deadline_wakeups.py +147 -0
- django_due-0.1.0/tests/capabilities/test_dependent_wake.py +371 -0
- django_due-0.1.0/tests/capabilities/test_eligibility.py +258 -0
- django_due-0.1.0/tests/capabilities/test_eligibility_evidence.py +104 -0
- django_due-0.1.0/tests/capabilities/test_input_fields.py +108 -0
- django_due-0.1.0/tests/capabilities/test_observation_recovery.py +284 -0
- django_due-0.1.0/tests/capabilities/test_observation_smoke.py +106 -0
- django_due-0.1.0/tests/capabilities/test_observations.py +61 -0
- django_due-0.1.0/tests/capabilities/test_operation_observed_evidence.py +84 -0
- django_due-0.1.0/tests/capabilities/test_operation_recovery_isolation.py +109 -0
- django_due-0.1.0/tests/capabilities/test_operation_rejection_evidence.py +254 -0
- django_due-0.1.0/tests/capabilities/test_provider_calls.py +66 -0
- django_due-0.1.0/tests/capabilities/test_recover_dispatch_clock.py +94 -0
- django_due-0.1.0/tests/capabilities/test_recovery_deferral.py +497 -0
- django_due-0.1.0/tests/capabilities/test_required_completion.py +304 -0
- django_due-0.1.0/tests/capabilities/test_scheduled_action_schedule_at.py +110 -0
- django_due-0.1.0/tests/comparison/__init__.py +0 -0
- django_due-0.1.0/tests/comparison/test_books.py +102 -0
- django_due-0.1.0/tests/conformance/__init__.py +1 -0
- django_due-0.1.0/tests/conformance/bindings.py +136 -0
- django_due-0.1.0/tests/conformance/book_examples.py +234 -0
- django_due-0.1.0/tests/conformance/catalog_examples.py +97 -0
- django_due-0.1.0/tests/conformance/conftest.py +41 -0
- django_due-0.1.0/tests/conformance/debt_baseline.yaml +14 -0
- django_due-0.1.0/tests/conformance/document_examples.py +147 -0
- django_due-0.1.0/tests/conformance/index_examples.py +22 -0
- django_due-0.1.0/tests/conformance/order_examples.py +146 -0
- django_due-0.1.0/tests/conformance/scheduled_examples.py +172 -0
- django_due-0.1.0/tests/conformance/test_application_binding_scopes.py +68 -0
- django_due-0.1.0/tests/conformance/test_background_transport.py +74 -0
- django_due-0.1.0/tests/conformance/test_background_work_failure_accounting.py +398 -0
- django_due-0.1.0/tests/conformance/test_background_work_frozen_clock_skew.py +33 -0
- django_due-0.1.0/tests/conformance/test_background_work_provider_acceptance.py +43 -0
- django_due-0.1.0/tests/conformance/test_book_contracts.py +13 -0
- django_due-0.1.0/tests/conformance/test_books_contract_controls.py +72 -0
- django_due-0.1.0/tests/conformance/test_catalog_contract.py +8 -0
- django_due-0.1.0/tests/conformance/test_ci_evidence.py +120 -0
- django_due-0.1.0/tests/conformance/test_classified_failures.py +134 -0
- django_due-0.1.0/tests/conformance/test_concurrent_delivery.py +362 -0
- django_due-0.1.0/tests/conformance/test_conformance_collection_declared_scenarios.py +138 -0
- django_due-0.1.0/tests/conformance/test_conformance_collection_missing_proofs.py +172 -0
- django_due-0.1.0/tests/conformance/test_conformance_collection_outcomes.py +119 -0
- django_due-0.1.0/tests/conformance/test_conformance_collection_reports.py +314 -0
- django_due-0.1.0/tests/conformance/test_conformance_enrollment.py +743 -0
- django_due-0.1.0/tests/conformance/test_contract.py +53 -0
- django_due-0.1.0/tests/conformance/test_database_proof_controls.py +411 -0
- django_due-0.1.0/tests/conformance/test_discovery_admissibility.py +125 -0
- django_due-0.1.0/tests/conformance/test_discovery_completeness.py +51 -0
- django_due-0.1.0/tests/conformance/test_document_contract.py +10 -0
- django_due-0.1.0/tests/conformance/test_document_process_control.py +22 -0
- django_due-0.1.0/tests/conformance/test_evidence_proofs_require_due_work.py +34 -0
- django_due-0.1.0/tests/conformance/test_failing_external_call.py +21 -0
- django_due-0.1.0/tests/conformance/test_host.py +62 -0
- django_due-0.1.0/tests/conformance/test_immutable_inputs_claim.py +254 -0
- django_due-0.1.0/tests/conformance/test_lock_order_recorder.py +64 -0
- django_due-0.1.0/tests/conformance/test_nested_project_inventory.py +24 -0
- django_due-0.1.0/tests/conformance/test_observation_contract.py +159 -0
- django_due-0.1.0/tests/conformance/test_operation_uncertainty.py +58 -0
- django_due-0.1.0/tests/conformance/test_order_contract.py +8 -0
- django_due-0.1.0/tests/conformance/test_persistent_retry.py +60 -0
- django_due-0.1.0/tests/conformance/test_process_outcomes.py +32 -0
- django_due-0.1.0/tests/conformance/test_provider_probe.py +172 -0
- django_due-0.1.0/tests/conformance/test_provider_seam.py +227 -0
- django_due-0.1.0/tests/conformance/test_query_scale.py +292 -0
- django_due-0.1.0/tests/conformance/test_recovery_isolation_phase_proofs.py +27 -0
- django_due-0.1.0/tests/conformance/test_registration_scopes.py +33 -0
- django_due-0.1.0/tests/conformance/test_scheduled_contract.py +8 -0
- django_due-0.1.0/tests/conformance/test_scheduler_adapters.py +176 -0
- django_due-0.1.0/tests/conformance/test_synchronous_caller_scenario.py +126 -0
- django_due-0.1.0/tests/conformance/test_terminal_example.py +71 -0
- django_due-0.1.0/tests/declarations/__init__.py +1 -0
- django_due-0.1.0/tests/declarations/test_declarations.py +332 -0
- django_due-0.1.0/tests/declarations/test_mirror_receipts.py +116 -0
- django_due-0.1.0/tests/declarations/test_simple_callbacks.py +160 -0
- django_due-0.1.0/tests/evidence/__init__.py +1 -0
- django_due-0.1.0/tests/evidence/test_canonical_receipt_storage.py +99 -0
- django_due-0.1.0/tests/evidence/test_evidence_histories.py +442 -0
- django_due-0.1.0/tests/examples/__init__.py +0 -0
- django_due-0.1.0/tests/examples/books_support.py +41 -0
- django_due-0.1.0/tests/examples/file_support.py +37 -0
- django_due-0.1.0/tests/examples/test_books.py +77 -0
- django_due-0.1.0/tests/examples/test_catalog.py +41 -0
- django_due-0.1.0/tests/examples/test_celery_migration.py +99 -0
- django_due-0.1.0/tests/examples/test_orders.py +48 -0
- django_due-0.1.0/tests/examples/test_revision_storage.py +148 -0
- django_due-0.1.0/tests/examples/test_scheduled.py +146 -0
- django_due-0.1.0/tests/examples/test_scheduled_migration.py +29 -0
- django_due-0.1.0/tests/examples/test_startup.py +47 -0
- django_due-0.1.0/tests/examples/test_submission_keys.py +123 -0
- django_due-0.1.0/tests/harness/__init__.py +6 -0
- django_due-0.1.0/tests/harness/book_process.py +45 -0
- django_due-0.1.0/tests/harness/broker.py +42 -0
- django_due-0.1.0/tests/harness/collection_sessions.py +293 -0
- django_due-0.1.0/tests/harness/comparison_process.py +46 -0
- django_due-0.1.0/tests/harness/dependents.py +118 -0
- django_due-0.1.0/tests/harness/document_process.py +33 -0
- django_due-0.1.0/tests/harness/enrollment.py +118 -0
- django_due-0.1.0/tests/harness/evidence.py +40 -0
- django_due-0.1.0/tests/harness/gated.py +13 -0
- django_due-0.1.0/tests/harness/observation.py +106 -0
- django_due-0.1.0/tests/harness/operation.py +97 -0
- django_due-0.1.0/tests/harness/primitive.py +147 -0
- django_due-0.1.0/tests/harness/processes.py +32 -0
- django_due-0.1.0/tests/harness/registrations.py +5 -0
- django_due-0.1.0/tests/harness/scheduled_process.py +44 -0
- django_due-0.1.0/tests/integration/processes.py +39 -0
- django_due-0.1.0/tests/integration/test_books_live.py +100 -0
- django_due-0.1.0/tests/integration/test_books_worker.py +45 -0
- django_due-0.1.0/tests/integration/test_celery_migration.py +30 -0
- django_due-0.1.0/tests/integration/test_celery_worker.py +41 -0
- django_due-0.1.0/tests/integration/test_richer_examples.py +57 -0
- django_due-0.1.0/tests/integration/test_scheduled_live.py +90 -0
- django_due-0.1.0/tests/integration/worker.py +76 -0
- django_due-0.1.0/tests/runtime/__init__.py +1 -0
- django_due-0.1.0/tests/runtime/test_check_command.py +75 -0
- django_due-0.1.0/tests/runtime/test_delivery_budget.py +116 -0
- django_due-0.1.0/tests/runtime/test_deployment_contracts.py +77 -0
- django_due-0.1.0/tests/runtime/test_execution.py +269 -0
- django_due-0.1.0/tests/runtime/test_lock_owner_of_work.py +77 -0
- django_due-0.1.0/tests/runtime/test_metric_failures.py +51 -0
- django_due-0.1.0/tests/runtime/test_private_delivery_lease.py +94 -0
- django_due-0.1.0/tests/runtime/test_private_delivery_page.py +78 -0
- django_due-0.1.0/tests/runtime/test_recovery_pass.py +292 -0
- django_due-0.1.0/tests/runtime/test_registry.py +174 -0
- django_due-0.1.0/tests/runtime/test_retry_policy.py +154 -0
- django_due-0.1.0/tests/runtime/test_setup.py +80 -0
- django_due-0.1.0/tests/runtime/test_status_command.py +69 -0
- django_due-0.1.0/tests/runtime/test_transport.py +134 -0
- django_due-0.1.0/tests/settings.py +7 -0
- django_due-0.1.0/tests/test_completion_lease.py +242 -0
- django_due-0.1.0/tests/test_completion_lease_histories.py +195 -0
- django_due-0.1.0/tests/test_primitive_independence.py +163 -0
- django_due-0.1.0/tests/test_provider_idempotency_key.py +32 -0
- django_due-0.1.0/tests/test_testing.py +126 -0
- django_due-0.1.0/uv.lock +1114 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Behavior
|
|
2
|
+
|
|
3
|
+
Describe the concrete problem and resulting behavior, including the relevant
|
|
4
|
+
failure or recovery history.
|
|
5
|
+
|
|
6
|
+
## Validation
|
|
7
|
+
|
|
8
|
+
Name the checks run and the limits of what they prove. For an obligation-contract
|
|
9
|
+
change, include the profile report and any newly unassessed guarantees.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
|
+
- uses: astral-sh/setup-uv@v7
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
- run: uv sync --locked --only-group lint
|
|
21
|
+
- run: uv run --no-sync ruff check .
|
|
22
|
+
- run: uv run --no-sync ruff format --check .
|
|
23
|
+
- run: uv run --no-sync pre-commit validate-config
|
|
24
|
+
- name: Validate GitHub Actions
|
|
25
|
+
run: docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.7 -color
|
|
26
|
+
|
|
27
|
+
typecheck:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v7
|
|
31
|
+
- uses: astral-sh/setup-uv@v7
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
- run: uv sync --locked
|
|
35
|
+
- run: uv run --no-sync pyrefly check
|
|
36
|
+
|
|
37
|
+
tests:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
timeout-minutes: 10
|
|
40
|
+
strategy:
|
|
41
|
+
fail-fast: false
|
|
42
|
+
matrix:
|
|
43
|
+
django: [locked, minimum]
|
|
44
|
+
services:
|
|
45
|
+
postgres:
|
|
46
|
+
image: postgres:17
|
|
47
|
+
env:
|
|
48
|
+
POSTGRES_USER: due
|
|
49
|
+
POSTGRES_PASSWORD: due
|
|
50
|
+
POSTGRES_DB: due
|
|
51
|
+
ports: ["5432:5432"]
|
|
52
|
+
options: >-
|
|
53
|
+
--health-cmd "pg_isready -U due"
|
|
54
|
+
--health-interval 5s
|
|
55
|
+
--health-timeout 5s
|
|
56
|
+
--health-retries 10
|
|
57
|
+
redis:
|
|
58
|
+
image: redis:7
|
|
59
|
+
ports: ["6379:6379"]
|
|
60
|
+
options: >-
|
|
61
|
+
--health-cmd "redis-cli ping"
|
|
62
|
+
--health-interval 5s
|
|
63
|
+
--health-timeout 5s
|
|
64
|
+
--health-retries 10
|
|
65
|
+
env:
|
|
66
|
+
DUE_DATABASE_URL: postgresql://due:due@localhost:5432/due
|
|
67
|
+
DUE_BROKER_URL: redis://localhost:6379/0
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v7
|
|
70
|
+
- uses: astral-sh/setup-uv@v7
|
|
71
|
+
with:
|
|
72
|
+
enable-cache: true
|
|
73
|
+
- run: uv sync --locked
|
|
74
|
+
- name: Exercise the declared Django lower bound
|
|
75
|
+
if: matrix.django == 'minimum'
|
|
76
|
+
run: uv pip install 'django==6.0.8'
|
|
77
|
+
- name: Run full suite including live web, worker and Beat recovery
|
|
78
|
+
run: uv run --no-sync pytest --due-work-check-fixtures --basetemp=test-results -p due.django.conformance.reporting --due-work-debt-baseline=tests/conformance/debt_baseline.yaml --due-work-profile-report=profiles.json --durable-work-report=effects.json --durable-observation-report=observations.json
|
|
79
|
+
- name: Require executed obligation guarantees
|
|
80
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract "Due replay-safe work table" --verified A B D I J
|
|
81
|
+
- name: Require complete application conformance
|
|
82
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract publish_document --verified A B D E H I J --effect-report effects.json --effect publish_document --required-effect-case "test_due_work_contract[process-document process death-assert_process_deaths_converge]"
|
|
83
|
+
- name: Require complete book indexing conformance
|
|
84
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract index_book --verified A B D H I J --effect-report effects.json --effect index_book --required-effect-case "test_immutable_inputs_hold[admission-create book]" --required-effect-case "test_immutable_inputs_hold[admission_failure-create book]" --required-effect-case "test_due_work_contract[process-book indexing and publication process death-assert_process_deaths_converge]"
|
|
85
|
+
- name: Require complete book publication conformance
|
|
86
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract publish_book --verified A B D H J --effect-report effects.json --effect publish_book --required-effect-case "test_immutable_inputs_hold[producer-index settlement]"
|
|
87
|
+
- name: Require catalog projection conformance
|
|
88
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract project_catalog --verified A B D E H I J --effect-report effects.json --effect project_catalog
|
|
89
|
+
# Non-repeatable orders decline harmless replay and retain evidence indefinitely.
|
|
90
|
+
- name: Require observed print-order conformance
|
|
91
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract print_order --verified A B C I J --effect-report effects.json --effect print_order
|
|
92
|
+
- name: Require scheduled publication conformance
|
|
93
|
+
run: uv run --no-sync python scripts/check_adoption_report.py profiles.json --contract publish_at_deadline --verified A B E H I J --effect-report effects.json --effect publish_at_deadline --required-effect-case "test_due_work_contract[process-scheduled publication process death-assert_process_deaths_converge]"
|
|
94
|
+
- name: Validate application setup
|
|
95
|
+
run: uv run --no-sync python -m django due_check
|
|
96
|
+
env:
|
|
97
|
+
DJANGO_SETTINGS_MODULE: examples.settings
|
|
98
|
+
- run: uv run --no-sync python -m django makemigrations --check --dry-run
|
|
99
|
+
env:
|
|
100
|
+
DJANGO_SETTINGS_MODULE: examples.settings
|
|
101
|
+
- uses: actions/upload-artifact@v7
|
|
102
|
+
if: always()
|
|
103
|
+
with:
|
|
104
|
+
name: obligation-profiles-${{ matrix.django }}
|
|
105
|
+
path: |
|
|
106
|
+
profiles.json
|
|
107
|
+
effects.json
|
|
108
|
+
observations.json
|
|
109
|
+
test-results/**/*.log
|
|
110
|
+
if-no-files-found: error
|
|
111
|
+
|
|
112
|
+
build:
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
steps:
|
|
115
|
+
- uses: actions/checkout@v7
|
|
116
|
+
with:
|
|
117
|
+
fetch-depth: 0
|
|
118
|
+
- uses: astral-sh/setup-uv@v7
|
|
119
|
+
with:
|
|
120
|
+
enable-cache: true
|
|
121
|
+
- run: uv build
|
|
122
|
+
- run: uvx --from twine twine check --strict dist/*
|
|
123
|
+
- name: Install the wheel without development dependencies
|
|
124
|
+
run: |
|
|
125
|
+
uv venv /tmp/due-wheel
|
|
126
|
+
uv pip install --python /tmp/due-wheel dist/*.whl
|
|
127
|
+
/tmp/due-wheel/bin/python -I scripts/check_wheel.py
|
|
128
|
+
- uses: actions/upload-artifact@v7
|
|
129
|
+
with:
|
|
130
|
+
name: distributions
|
|
131
|
+
path: dist/
|
|
132
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: PR title
|
|
2
|
+
|
|
3
|
+
# Conventional titles keep the public change history readable.
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
pull_request_target:
|
|
7
|
+
types: [opened, edited, synchronize, reopened]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
pull-requests: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
conventional-commit:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
# Reads only the title through the API; it never checks out the pull request's code.
|
|
17
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
18
|
+
env:
|
|
19
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
20
|
+
with:
|
|
21
|
+
types: |
|
|
22
|
+
feat
|
|
23
|
+
fix
|
|
24
|
+
perf
|
|
25
|
+
revert
|
|
26
|
+
docs
|
|
27
|
+
refactor
|
|
28
|
+
test
|
|
29
|
+
build
|
|
30
|
+
ci
|
|
31
|
+
chore
|
|
32
|
+
requireScope: false
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# After normal CI succeeds on main, release-please updates a release PR holding the next
|
|
4
|
+
# SemVer version and changelog, derived from Conventional Commit messages.
|
|
5
|
+
# Merging that PR tags vX.Y.Z and creates the GitHub release; this workflow
|
|
6
|
+
# then builds that exact tag and publishes it to PyPI with Trusted Publishing
|
|
7
|
+
# (OIDC, no stored token). See RELEASING.md.
|
|
8
|
+
#
|
|
9
|
+
# workflow_dispatch publishes an existing tag to TestPyPI or PyPI (a rehearsal,
|
|
10
|
+
# or a publish that failed after tagging), or, with no tag and TestPyPI, the
|
|
11
|
+
# dispatched commit's .devN version, which PyPI never receives.
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
workflow_run:
|
|
15
|
+
workflows: [CI]
|
|
16
|
+
branches: [main]
|
|
17
|
+
types: [completed]
|
|
18
|
+
workflow_dispatch:
|
|
19
|
+
inputs:
|
|
20
|
+
tag:
|
|
21
|
+
description: "Release tag to publish, for example v0.1.0. Empty with testpypi: publish this commit's dev version"
|
|
22
|
+
required: false
|
|
23
|
+
default: ""
|
|
24
|
+
index:
|
|
25
|
+
description: "Where to publish"
|
|
26
|
+
type: choice
|
|
27
|
+
options: [testpypi, pypi]
|
|
28
|
+
default: testpypi
|
|
29
|
+
|
|
30
|
+
permissions: {}
|
|
31
|
+
|
|
32
|
+
concurrency:
|
|
33
|
+
group: release
|
|
34
|
+
cancel-in-progress: false
|
|
35
|
+
|
|
36
|
+
jobs:
|
|
37
|
+
release-please:
|
|
38
|
+
if: >-
|
|
39
|
+
github.event_name == 'workflow_run'
|
|
40
|
+
&& github.event.workflow_run.event == 'push'
|
|
41
|
+
&& github.event.workflow_run.conclusion == 'success'
|
|
42
|
+
&& github.event.workflow_run.head_repository.full_name == github.repository
|
|
43
|
+
environment: release-automation
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
permissions:
|
|
46
|
+
contents: write
|
|
47
|
+
pull-requests: write
|
|
48
|
+
outputs:
|
|
49
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
50
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
51
|
+
steps:
|
|
52
|
+
- name: Only release the tested main head
|
|
53
|
+
id: current
|
|
54
|
+
uses: actions/github-script@v8
|
|
55
|
+
with:
|
|
56
|
+
script: |
|
|
57
|
+
const {data: branch} = await github.rest.repos.getBranch({...context.repo, branch: 'main'});
|
|
58
|
+
core.setOutput('matches', branch.commit.sha === context.payload.workflow_run.head_sha);
|
|
59
|
+
- name: Require release PR authentication
|
|
60
|
+
env:
|
|
61
|
+
HAS_RELEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN != '' }}
|
|
62
|
+
run: |
|
|
63
|
+
if [[ "$HAS_RELEASE_TOKEN" != "true" ]]; then
|
|
64
|
+
echo "::error::Configure RELEASE_PLEASE_TOKEN in the main-only release-automation environment."
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
- id: release
|
|
68
|
+
if: steps.current.outputs.matches == 'true'
|
|
69
|
+
uses: googleapis/release-please-action@v4
|
|
70
|
+
with:
|
|
71
|
+
# A non-GITHUB_TOKEN credential triggers ordinary PR CI. The main-only
|
|
72
|
+
# environment keeps it unavailable to pull-request test jobs.
|
|
73
|
+
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
|
|
74
|
+
target-branch: main
|
|
75
|
+
config-file: release-please-config.json
|
|
76
|
+
manifest-file: .release-please-manifest.json
|
|
77
|
+
|
|
78
|
+
build:
|
|
79
|
+
needs: release-please
|
|
80
|
+
if: >-
|
|
81
|
+
always() && (
|
|
82
|
+
(github.event_name == 'workflow_run' && needs.release-please.result == 'success' && needs.release-please.outputs.release_created == 'true')
|
|
83
|
+
|| github.event_name == 'workflow_dispatch'
|
|
84
|
+
)
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
permissions:
|
|
87
|
+
contents: read
|
|
88
|
+
actions: read
|
|
89
|
+
outputs:
|
|
90
|
+
tag: ${{ steps.tag.outputs.tag }}
|
|
91
|
+
version: ${{ steps.built.outputs.version }}
|
|
92
|
+
steps:
|
|
93
|
+
- id: tag
|
|
94
|
+
env:
|
|
95
|
+
TAG: ${{ needs.release-please.outputs.tag_name || inputs.tag }}
|
|
96
|
+
INDEX: ${{ inputs.index || 'pypi' }}
|
|
97
|
+
run: |
|
|
98
|
+
if [[ -z "$TAG" ]]; then
|
|
99
|
+
# Only a TestPyPI rehearsal may publish an untagged commit, as its .devN version.
|
|
100
|
+
if [[ "$INDEX" != "testpypi" ]]; then
|
|
101
|
+
echo "::error::publishing to PyPI needs a release tag" >&2
|
|
102
|
+
exit 1
|
|
103
|
+
fi
|
|
104
|
+
echo "tag=" >> "$GITHUB_OUTPUT"
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
# A release is a plain SemVer core version: vMAJOR.MINOR.PATCH.
|
|
108
|
+
if [[ ! "$TAG" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
|
|
109
|
+
echo "::error::'$TAG' is not a release tag of the form vMAJOR.MINOR.PATCH" >&2
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
113
|
+
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
|
114
|
+
- uses: actions/checkout@v7
|
|
115
|
+
with:
|
|
116
|
+
ref: ${{ steps.tag.outputs.tag || github.sha }}
|
|
117
|
+
# The version is read from the tag, so the tag must be present.
|
|
118
|
+
fetch-depth: 0
|
|
119
|
+
# Check the resolved tag, including on manual retries: a green run for a
|
|
120
|
+
# different commit (or a PR) must never authorize a production release.
|
|
121
|
+
- name: Require normal CI on the exact release commit
|
|
122
|
+
if: inputs.index != 'testpypi'
|
|
123
|
+
env:
|
|
124
|
+
GH_TOKEN: ${{ github.token }}
|
|
125
|
+
run: |
|
|
126
|
+
source_sha=$(git rev-parse HEAD)
|
|
127
|
+
count=$(gh api "repos/$GITHUB_REPOSITORY/actions/workflows/ci.yml/runs?branch=main&event=push&status=success&head_sha=$source_sha" --jq '.total_count')
|
|
128
|
+
if [[ "$count" -lt 1 ]]; then
|
|
129
|
+
echo "::error::No successful main CI run for release commit $source_sha. Re-run its CI before publishing."
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
- uses: astral-sh/setup-uv@v7
|
|
133
|
+
- run: uv build
|
|
134
|
+
- run: uvx --from twine twine check --strict dist/*
|
|
135
|
+
- name: The built version is the tag
|
|
136
|
+
if: steps.tag.outputs.tag != ''
|
|
137
|
+
env:
|
|
138
|
+
VERSION: ${{ steps.tag.outputs.version }}
|
|
139
|
+
run: |
|
|
140
|
+
ls dist
|
|
141
|
+
test -f "dist/django_due-${VERSION}-py3-none-any.whl"
|
|
142
|
+
test -f "dist/django_due-${VERSION}.tar.gz"
|
|
143
|
+
- name: An untagged build is a dev release
|
|
144
|
+
if: steps.tag.outputs.tag == ''
|
|
145
|
+
run: |
|
|
146
|
+
ls dist
|
|
147
|
+
wheel=$(basename dist/*.whl)
|
|
148
|
+
[[ "$wheel" =~ ^django_due-[0-9]+\.[0-9]+(\.[0-9]+)?\.dev[0-9]+-py3-none-any\.whl$ ]]
|
|
149
|
+
- id: built
|
|
150
|
+
run: |
|
|
151
|
+
wheel=$(basename dist/*.whl)
|
|
152
|
+
version=${wheel#django_due-}
|
|
153
|
+
echo "version=${version%-py3-none-any.whl}" >> "$GITHUB_OUTPUT"
|
|
154
|
+
- name: Install the wheel without development dependencies
|
|
155
|
+
run: |
|
|
156
|
+
uv venv /tmp/wheel && uv pip install --python /tmp/wheel dist/*.whl
|
|
157
|
+
/tmp/wheel/bin/python -I scripts/check_wheel.py
|
|
158
|
+
- name: Require the testing extra to resolve from published packages
|
|
159
|
+
# Development CI uses the reviewed Git source. A release must also be
|
|
160
|
+
# installable by ordinary PyPI consumers, without uv.sources or Git.
|
|
161
|
+
run: |
|
|
162
|
+
wheel=(dist/*.whl)
|
|
163
|
+
uv pip install --no-sources --default-index https://pypi.org/simple --python /tmp/wheel "${wheel[0]}[testing]"
|
|
164
|
+
uv pip check --python /tmp/wheel
|
|
165
|
+
- uses: actions/upload-artifact@v7
|
|
166
|
+
with:
|
|
167
|
+
name: dist
|
|
168
|
+
path: dist/
|
|
169
|
+
if-no-files-found: error
|
|
170
|
+
|
|
171
|
+
publish-pypi:
|
|
172
|
+
needs: build
|
|
173
|
+
if: >-
|
|
174
|
+
always() && needs.build.result == 'success'
|
|
175
|
+
&& (github.event_name == 'workflow_run' || inputs.index == 'pypi')
|
|
176
|
+
runs-on: ubuntu-latest
|
|
177
|
+
environment:
|
|
178
|
+
name: pypi
|
|
179
|
+
url: https://pypi.org/project/django-due/${{ needs.build.outputs.version }}/
|
|
180
|
+
permissions:
|
|
181
|
+
id-token: write
|
|
182
|
+
steps:
|
|
183
|
+
- uses: actions/download-artifact@v8
|
|
184
|
+
with:
|
|
185
|
+
name: dist
|
|
186
|
+
path: dist/
|
|
187
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
188
|
+
|
|
189
|
+
publish-testpypi:
|
|
190
|
+
needs: build
|
|
191
|
+
if: >-
|
|
192
|
+
always() && needs.build.result == 'success'
|
|
193
|
+
&& github.event_name == 'workflow_dispatch' && inputs.index == 'testpypi'
|
|
194
|
+
runs-on: ubuntu-latest
|
|
195
|
+
environment:
|
|
196
|
+
name: testpypi
|
|
197
|
+
url: https://test.pypi.org/project/django-due/${{ needs.build.outputs.version }}/
|
|
198
|
+
permissions:
|
|
199
|
+
id-token: write
|
|
200
|
+
steps:
|
|
201
|
+
- uses: actions/download-artifact@v8
|
|
202
|
+
with:
|
|
203
|
+
name: dist
|
|
204
|
+
path: dist/
|
|
205
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
206
|
+
with:
|
|
207
|
+
repository-url: https://test.pypi.org/legacy/
|
|
208
|
+
|
|
209
|
+
attach-to-release:
|
|
210
|
+
needs: [build, publish-pypi]
|
|
211
|
+
if: always() && needs.publish-pypi.result == 'success' && needs.build.outputs.tag != ''
|
|
212
|
+
runs-on: ubuntu-latest
|
|
213
|
+
permissions:
|
|
214
|
+
contents: write
|
|
215
|
+
steps:
|
|
216
|
+
- uses: actions/download-artifact@v8
|
|
217
|
+
with:
|
|
218
|
+
name: dist
|
|
219
|
+
path: dist/
|
|
220
|
+
- env:
|
|
221
|
+
GH_TOKEN: ${{ github.token }}
|
|
222
|
+
TAG: ${{ needs.build.outputs.tag }}
|
|
223
|
+
run: gh release upload "$TAG" dist/* --clobber --repo "$GITHUB_REPOSITORY"
|
|
224
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
minimum_pre_commit_version: '4.3.0'
|
|
2
|
+
repos:
|
|
3
|
+
- repo: local
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff-check
|
|
6
|
+
name: Ruff lint (uv.lock)
|
|
7
|
+
entry: uv run --locked ruff check --fix
|
|
8
|
+
language: system
|
|
9
|
+
types_or: [python, pyi]
|
|
10
|
+
- id: ruff-format
|
|
11
|
+
name: Ruff format (uv.lock)
|
|
12
|
+
entry: uv run --locked ruff format
|
|
13
|
+
language: system
|
|
14
|
+
types_or: [python, pyi, markdown]
|
|
15
|
+
- id: pyrefly
|
|
16
|
+
name: Pyrefly project check (uv.lock)
|
|
17
|
+
entry: uv run --locked pyrefly check
|
|
18
|
+
language: system
|
|
19
|
+
pass_filenames: false
|
|
20
|
+
files: '(^pyproject\.toml$|^uv\.lock$|\.pyi?$)'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{".":"0.1.0"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-10-12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add a runnable books example with recovery proofs ([57b94db](https://github.com/gigaverse-app/due/commit/57b94dbc98fda1d95745d63d81b7408cdb940ee3))
|
|
9
|
+
* add books indexing demo and recoverable handoff proofs ([dd941a3](https://github.com/gigaverse-app/due/commit/dd941a317638938e424e823e07a5bee74841ee37))
|
|
10
|
+
* add comparative recovery demos and setup diagnostics ([20adee4](https://github.com/gigaverse-app/due/commit/20adee48526f247690dc7e088434e68f3a09f6ed))
|
|
11
|
+
* add executable Celery comparison and pin Books port reference ([3d62279](https://github.com/gigaverse-app/due/commit/3d6227905e20554b851ed8bdaab09b9fffdaf810))
|
|
12
|
+
* add executable migration demo comparisons ([5e2aba9](https://github.com/gigaverse-app/due/commit/5e2aba9cf79d9481b4327e099b2fbb11634edf1c))
|
|
13
|
+
* add scheduled publication with deadline hints and submission keys ([5795f0c](https://github.com/gigaverse-app/due/commit/5795f0c5db8c49618ddb806ec189d64e17a19140))
|
|
14
|
+
* complete backend harness adapters and proof controls ([141af43](https://github.com/gigaverse-app/due/commit/141af432f6cd1a2203c9d9ead0caa518274edf47))
|
|
15
|
+
* complete discovery proofs and provider seam bindings ([87e7b12](https://github.com/gigaverse-app/due/commit/87e7b120396796c0733e411fdf503797c3a90d3a))
|
|
16
|
+
* complete work-table tooling and contributor workflow ([aa5fbfc](https://github.com/gigaverse-app/due/commit/aa5fbfcd8aac919696430e94915a2643f78fbb14))
|
|
17
|
+
* demonstrate and compare application recovery guarantees ([0a19778](https://github.com/gigaverse-app/due/commit/0a19778975824c735a784b60ad204468b388a39b))
|
|
18
|
+
* demonstrate scheduled publication with cancellation and recovery proofs ([0a3e38a](https://github.com/gigaverse-app/due/commit/0a3e38a91f93b72e89a8aa00d174fe52852a65a6))
|
|
19
|
+
* every work table can declare its provider outcome matrix ([#27](https://github.com/gigaverse-app/due/issues/27)) ([5ee2b7b](https://github.com/gigaverse-app/due/commit/5ee2b7b1d3d6d9f49f4bf21cbe965e3f603b17a2))
|
|
20
|
+
* extract Django work-table execution and recovery into Due ([a1e30be](https://github.com/gigaverse-app/due/commit/a1e30bec92dd03fd382ded0a6ad799b87c320914))
|
|
21
|
+
* finish Beat and interleaving harness adapters ([ed3de62](https://github.com/gigaverse-app/due/commit/ed3de62ea03b8755cd53c913652b75a5d57eb9f9))
|
|
22
|
+
* integrate adopter proofs and recover lifecycle tooling ([1204181](https://github.com/gigaverse-app/due/commit/1204181e06018dc5778bf146444824595ed6f5ec))
|
|
23
|
+
* port application-bound work-table conformance harness ([65e0bcf](https://github.com/gigaverse-app/due/commit/65e0bcfe426c9e663aec4ae5c71398965dde3269))
|
|
24
|
+
* port application-bound work-table conformance harness ([d682f93](https://github.com/gigaverse-app/due/commit/d682f93cd8c1862f0f5b49e2e6cca9957db2f742))
|
|
25
|
+
* preserve application fatal recovery errors and bind host proofs ([96d7ab2](https://github.com/gigaverse-app/due/commit/96d7ab2427076a810ff687766ac88e725c579064))
|
|
26
|
+
* preserve application recovery failures and document proof integration ([ab8ff31](https://github.com/gigaverse-app/due/commit/ab8ff31104fa2e42a997a3637e04982665789a13))
|
|
27
|
+
* preserve backend handoff recovery and harness mutation controls ([43b88af](https://github.com/gigaverse-app/due/commit/43b88af5f92ab324f9e49c576eb3599c8bb53e32))
|
|
28
|
+
* preserve deployment contracts and stronger work-table bindings ([a241d70](https://github.com/gigaverse-app/due/commit/a241d70e5e3110ee3c78e389d415b76e838f33ed))
|
|
29
|
+
* preserve discovery completeness and failed recovery evidence ([65d4a86](https://github.com/gigaverse-app/due/commit/65d4a8688fc78b4ec7d83b1f66c63ce9b9fb9c4f))
|
|
30
|
+
* prove application outcomes and publish immutable files without replay writes ([92bfacd](https://github.com/gigaverse-app/due/commit/92bfacdb2f23b1b1959e40ae02364fef9103edee))
|
|
31
|
+
* prove books input stability and require demo replay outcomes ([b19425e](https://github.com/gigaverse-app/due/commit/b19425eeda04c2a090e300faab733269caafcd53))
|
|
32
|
+
* prove immutable input claims against admission and recovery ([ac847ca](https://github.com/gigaverse-app/due/commit/ac847ca05ef3bf7afbe2f3c54c684e5014ce7de6))
|
|
33
|
+
* publish django-due through manually approved releases ([#26](https://github.com/gigaverse-app/due/issues/26)) ([bdcb1e6](https://github.com/gigaverse-app/due/commit/bdcb1e657861412bf85b8ed56dec393b4454b230))
|
|
34
|
+
* restore work-table operator tooling and harden contributor checks ([2766c33](https://github.com/gigaverse-app/due/commit/2766c33f2456886bba0f9b6c29b17018dcd2178f))
|
|
35
|
+
* share typed provider probes and complete Celery setup ([6765a0a](https://github.com/gigaverse-app/due/commit/6765a0ab7f079d5fe2543e26bb9915848f7a43b2))
|
|
36
|
+
* simplify runtime and provider bindings ([d1ebe81](https://github.com/gigaverse-app/due/commit/d1ebe81bb815ccdd96070c84d17fb8db5718143b))
|
|
37
|
+
* unbounded work tables claim profile J through the persistent-failure proof ([d6c8a4b](https://github.com/gigaverse-app/due/commit/d6c8a4b9ddfb3215560b938c3dcd49dd7759a088))
|
|
38
|
+
* unbounded work tables claim profile J through the persistent-failure proof ([c642482](https://github.com/gigaverse-app/due/commit/c642482a7853dd130719382f3cb16f01c21b84ed))
|
|
39
|
+
* upstream native lifecycle and cutover integration improvements ([93ca10c](https://github.com/gigaverse-app/due/commit/93ca10cb8ae11a93e1e13b21f78e7a9a0e64ce4e))
|
|
40
|
+
* verify immutable input claims through production admission ([533530e](https://github.com/gigaverse-app/due/commit/533530e7377d3d32e749caaef387a38a6dcf919f))
|
|
41
|
+
* wake near deadlines without SQL hints and deduplicate submissions ([eaa043f](https://github.com/gigaverse-app/due/commit/eaa043f5140b531f044212065bcc596c59d5bb1d))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Bug fixes
|
|
45
|
+
|
|
46
|
+
* consume queued recovery in the comparison harness ([9a3003e](https://github.com/gigaverse-app/due/commit/9a3003e07389f1cdbd8b53bea1cebca84f100ad7))
|
|
47
|
+
* failing_external_call counts every provider entry ([f4c8202](https://github.com/gigaverse-app/due/commit/f4c820257a7211ca53d1ce2e65f4812dcb8ddf05))
|
|
48
|
+
* initialize the example Celery app in Django processes ([5baa593](https://github.com/gigaverse-app/due/commit/5baa5938bf8c731bfe808ba8fc6ba1dbd5721c95))
|
|
49
|
+
* keep gate recovery on the harness-owned broker ([286e694](https://github.com/gigaverse-app/due/commit/286e6943afbc1efce1fb1e35c49fdf17f3deb400))
|
|
50
|
+
* preserve delivery verdicts and consolidate recovery ownership ([810c0c0](https://github.com/gigaverse-app/due/commit/810c0c0e9591e04aa853f69e5d52f512e47fd586))
|
|
51
|
+
* preserve proof failures through adopter cleanup ([b862931](https://github.com/gigaverse-app/due/commit/b8629317003551c78c518ba899a721752d152497))
|
|
52
|
+
* register deadline recovery proof and validate final harness candidate ([424a446](https://github.com/gigaverse-app/due/commit/424a44635c2ffacf01e499d4d6c710fdc5f6b31f))
|
|
53
|
+
* retain adopter environment throughout crash histories ([f7b8713](https://github.com/gigaverse-app/due/commit/f7b871301d6ca376f39d43ae59449e0da343b9e1))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
### Performance
|
|
57
|
+
|
|
58
|
+
* publish immutable revisions cheaply with application outcome proofs ([f68e3e4](https://github.com/gigaverse-app/due/commit/f68e3e41098134c33fc0aab3fe351885c9157e30))
|
|
59
|
+
* remove per-publication staging directories without weakening recovery ([4ce9e34](https://github.com/gigaverse-app/due/commit/4ce9e3495068a3496e38f57587a23aa251f7f7bc))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
### Documentation
|
|
63
|
+
|
|
64
|
+
* add coming-from guides for Python background-work libraries ([a65ee04](https://github.com/gigaverse-app/due/commit/a65ee0471ab51b28a4cde5897ff928f3fee5e806))
|
|
65
|
+
* add focused coming-from guides for Python work libraries ([054e65c](https://github.com/gigaverse-app/due/commit/054e65c2a86101ca9ba7fa7c440e957788660222))
|
|
66
|
+
* audit backend migration readiness ([#6](https://github.com/gigaverse-app/due/issues/6)) ([07e4b8b](https://github.com/gigaverse-app/due/commit/07e4b8be06563130475679a6c81484aa3632a5c4))
|
|
67
|
+
* compare Python queues and document migration and shim boundaries ([0893cd5](https://github.com/gigaverse-app/due/commit/0893cd5797961c731dc12eeb79737f6756599e4d))
|
|
68
|
+
* establish in-repository example catalog ([599c43f](https://github.com/gigaverse-app/due/commit/599c43f637d6eb97e6513a2ee9c169a2c719c1e9))
|
|
69
|
+
* explain Due strengths, tradeoffs and evidence boundaries ([4e635bc](https://github.com/gigaverse-app/due/commit/4e635bcfd1dde336ff4a5ddd9bd5b5f3f5c8c5ae))
|
|
70
|
+
* explain Due strengths, tradeoffs and evidence boundaries ([2d8e2dd](https://github.com/gigaverse-app/due/commit/2d8e2dd7a7c0aca2eeacc1ee78fd87a3561854a8))
|
|
71
|
+
* explain Temporal parity gaps and scheduled demo tradeoffs ([4998a18](https://github.com/gigaverse-app/due/commit/4998a18de69f6946728796d413a60964a6c70efa))
|
|
72
|
+
* format migration examples and check Markdown before commit ([fc6978d](https://github.com/gigaverse-app/due/commit/fc6978dfd751daf892c0edae6e96ce8573f1d088))
|
|
73
|
+
* guide conformance adoption and separate public authoring APIs ([6e0c061](https://github.com/gigaverse-app/due/commit/6e0c061c3a339e96803ffa3d81fb30817f5a6bcb))
|
|
74
|
+
* introduce Due durable obligations library ([3ac929f](https://github.com/gigaverse-app/due/commit/3ac929f175d25de951125a219d41c20d1b3b00b4))
|
|
75
|
+
* keep concurrent runtime adoption audit separate ([118486f](https://github.com/gigaverse-app/due/commit/118486f7a430bbb56864342870522dffd302efd8))
|
|
76
|
+
* link deadline wakeup evidence and completed recovery checks ([3752750](https://github.com/gigaverse-app/due/commit/37527507b6c4a79a30ad635ae390bfe11a6039dd))
|
|
77
|
+
* pin the companion harness audit reference ([2f48257](https://github.com/gigaverse-app/due/commit/2f48257ee403f91009a29c6df015c9f89d758fd7))
|
|
78
|
+
* plan application outcome and provider replay proofs ([b06ba90](https://github.com/gigaverse-app/due/commit/b06ba90322f9bc2cee3af19c5a1a7f5ebbef6464))
|
|
79
|
+
* plan audit-driven integration and recovery guides ([62f8688](https://github.com/gigaverse-app/due/commit/62f868824649409407963ea4427396d5a9da7087))
|
|
80
|
+
* plan backend replacement contract parity ([086b1be](https://github.com/gigaverse-app/due/commit/086b1bead3aa5c09524f7db732f71cea6b94f77a))
|
|
81
|
+
* plan checked immutable-input parity ([10e9eb0](https://github.com/gigaverse-app/due/commit/10e9eb031645ee38b68dc349a1333ce4bcce852a))
|
|
82
|
+
* plan comparative recovery and richer application demos ([a9cde2a](https://github.com/gigaverse-app/due/commit/a9cde2a9f3263d51ceaf19f82553426438c2afd0))
|
|
83
|
+
* plan current backend parity controls ([f8bb0e7](https://github.com/gigaverse-app/due/commit/f8bb0e762e9f1175ddecb1d925c4d9a5c4baf98f))
|
|
84
|
+
* plan executable books convergence guarantees ([9bc29d7](https://github.com/gigaverse-app/due/commit/9bc29d7e9156747eaf35daafdfe8f2cef1184382))
|
|
85
|
+
* plan real adopter integration and third source audit ([24428dc](https://github.com/gigaverse-app/due/commit/24428dc029b04e15bff70567f8545587afb2a34d))
|
|
86
|
+
* plan runtime and provider binding improvements ([3d79a87](https://github.com/gigaverse-app/due/commit/3d79a8789ba1d0a68bbc853950fe5a0b087aca2a))
|
|
87
|
+
* plan scheduled publication demo and recovery proofs ([8fdd8a6](https://github.com/gigaverse-app/due/commit/8fdd8a64822b70a521b5b83f728daae0039731fe))
|
|
88
|
+
* plan work-table parity and contributor workflow ([3d581ef](https://github.com/gigaverse-app/due/commit/3d581ef78a0886a89e0690c4102ded8739ac2b02))
|
|
89
|
+
* record audit port verification and migration limits ([a6d9d1a](https://github.com/gigaverse-app/due/commit/a6d9d1aeab4646be4d210f5aa333d50c88688d46))
|
|
90
|
+
* record binding integrity and integration evidence ([bf95077](https://github.com/gigaverse-app/due/commit/bf95077a634f70d0e94e000e64930e7537d8f5ed))
|
|
91
|
+
* record comparison and recovery validation evidence ([65f7cdc](https://github.com/gigaverse-app/due/commit/65f7cdcedcb5997f056b586293f9bd98f9c755bb))
|
|
92
|
+
* record complete serial consumer validation ([92433ad](https://github.com/gigaverse-app/due/commit/92433adfb9934f8c6d758434edbc7571cb14960d))
|
|
93
|
+
* record completed package and backend parity checks ([d779b1c](https://github.com/gigaverse-app/due/commit/d779b1cc8d838865883a6915c3713dcf7fbe55e4))
|
|
94
|
+
* record scheduled publication recovery evidence ([ff87b07](https://github.com/gigaverse-app/due/commit/ff87b074a9e44391189a5246c356a9321f2139bb))
|
|
95
|
+
* record standalone verification and supported Django baseline ([22153f1](https://github.com/gigaverse-app/due/commit/22153f1281c7fe87b4a64f688bc246994c2f8c4f))
|
|
96
|
+
* record the publication demo Procrastinate provenance ([a896b12](https://github.com/gigaverse-app/due/commit/a896b128102aaf01dbe0df497259e893f188c9fc))
|
|
97
|
+
* record work-table parity verification ([f5b4464](https://github.com/gigaverse-app/due/commit/f5b446407d3fba8e428725067d722069e89fd2c0))
|
|
98
|
+
* show concrete APIs and code changes in migration guides ([205bde7](https://github.com/gigaverse-app/due/commit/205bde743c989bd1721cbd543cdef4dd9a453f4e))
|
|
99
|
+
* start competitor migration audit ([7d625a8](https://github.com/gigaverse-app/due/commit/7d625a82af8477abf6f0428ae9373dde1afb1e8d))
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Contributing to Due
|
|
2
|
+
|
|
3
|
+
Due uses Python 3.14 and uv. Install Docker (or supply dedicated PostgreSQL and
|
|
4
|
+
Redis instances), then:
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
uv sync --locked
|
|
8
|
+
uv run pre-commit install
|
|
9
|
+
docker compose up -d --wait
|
|
10
|
+
uv run pre-commit run --all-files
|
|
11
|
+
uv run pytest --due-work-require-assessed --due-work-profile-report=profiles.json
|
|
12
|
+
uv run python scripts/check_adoption_report.py profiles.json --contract "Due replay-safe work table" --verified A B D I J
|
|
13
|
+
DJANGO_SETTINGS_MODULE=examples.settings uv run python -m django makemigrations --check --dry-run
|
|
14
|
+
uv build
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`uv.lock` is committed. Dependency edits need `uv lock`; normal development and
|
|
18
|
+
CI use `--locked`. Pre-commit runs Ruff lint/format on staged Python files and
|
|
19
|
+
Pyrefly on the whole project. Hooks can modify formatting; review and stage those
|
|
20
|
+
changes before committing again. Database and worker tests run separately from
|
|
21
|
+
commit hooks so a commit does not depend on Docker availability.
|
|
22
|
+
|
|
23
|
+
Tests use real PostgreSQL. `pytest-django` creates and drops its test database;
|
|
24
|
+
the configured user must be allowed to create databases. The worker integration
|
|
25
|
+
tests also use Redis and separate Celery prefork processes. The live books
|
|
26
|
+
journeys additionally start a real Django HTTP server and Celery Beat, verifying
|
|
27
|
+
normal form submission and scheduled recovery of either lost notification. Set
|
|
28
|
+
`DUE_DATABASE_URL` and `DUE_BROKER_URL` for dedicated test services, or use the defaults in
|
|
29
|
+
[compose.yaml](compose.yaml). Stop local services with `docker compose down`.
|
|
30
|
+
|
|
31
|
+
## Changes and proofs
|
|
32
|
+
|
|
33
|
+
Keep the public API focused on work tables. The delivery lease in
|
|
34
|
+
`runtime/_delivery.py` is private machinery for observation workers; it is not a
|
|
35
|
+
public native-table composition API. Use [the capability guide](docs/capabilities.md)
|
|
36
|
+
to find the existing owner of behavior before adding another abstraction.
|
|
37
|
+
|
|
38
|
+
For behavioral fixes, first write a failing history at the boundary that broke:
|
|
39
|
+
commit, publication, provider call, evidence, or local settlement. Prefer real
|
|
40
|
+
transactions and selectors. Fault injection may replace transport or the
|
|
41
|
+
provider; it must not replace the production decision being proved. Include a
|
|
42
|
+
control that demonstrates the fault was reached, and observe the product result.
|
|
43
|
+
|
|
44
|
+
## Pull requests and CI
|
|
45
|
+
|
|
46
|
+
Use Conventional Commit titles (`feat:`, `fix:`, `docs:`, `test:`, `ci:`,
|
|
47
|
+
`refactor:`, `build:`, `perf:`, `revert:`, `chore:`), enforced by the PR-title
|
|
48
|
+
workflow. Explain the resulting behavior, relevant validation and limitations.
|
|
49
|
+
|
|
50
|
+
CI has independent lint/workflow validation, Pyrefly, distribution, and
|
|
51
|
+
PostgreSQL/Redis test jobs. The test suite runs against locked Django and the
|
|
52
|
+
minimum supported Django version, including the live HTTP/worker/Beat journeys.
|
|
53
|
+
Obligation reports, process logs and distributions are retained as run artifacts.
|
|
54
|
+
The distribution job builds through the sdist, then imports the wheel with
|
|
55
|
+
isolated Python and no development dependencies.
|
|
56
|
+
|
|
57
|
+
`main` requires `lint`, `typecheck`, `tests (locked)`, `tests (minimum)`,
|
|
58
|
+
`build` and `conventional-commit` to pass from GitHub Actions, with the branch
|
|
59
|
+
up to date before merging. These repository protections apply to administrators
|
|
60
|
+
too. Preserve these check names when changing CI, or update branch protection
|
|
61
|
+
together with the workflow.
|
|
62
|
+
|
|
63
|
+
To reproduce the installed-wheel check:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv build
|
|
67
|
+
uv venv /tmp/due-wheel
|
|
68
|
+
uv pip install --python /tmp/due-wheel dist/*.whl
|
|
69
|
+
/tmp/due-wheel/bin/python -I scripts/check_wheel.py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Releases are not automatic yet; the GitHub installation in the README is the
|
|
73
|
+
supported distribution path. Creating a public repository does not reserve its
|
|
74
|
+
PyPI package name. Configure and verify PyPI ownership and Trusted Publishing
|
|
75
|
+
before adding a release workflow that uploads distributions.
|