From 7bded694365c938fe2cf7e79429d64d9fd6be8a1 Mon Sep 17 00:00:00 2001 From: hsilan Date: Fri, 22 May 2026 13:26:17 -0700 Subject: [PATCH 1/2] feat(sdk): monorepo repository to add new otel plugin package --- .github/scripts/ci-checks.sh | 39 +++++-- .github/workflows/ci.yml | 40 ++++++- .github/workflows/deploy-examples.yml | 9 +- .github/workflows/integration-tests.yml | 12 +- .github/workflows/pypi-publish.yml | 47 ++++---- .github/workflows/sync-package.yml | 72 ------------ .gitignore | 5 +- CONTRIBUTING.md | 39 ++++++- RELEASING.md | 106 ++++++++++++++++++ .../README.md | 47 ++++++++ .../pyproject.toml | 100 +++++++++++++++++ .../__about__.py | 4 + .../__init__.py | 8 ++ .../py.typed | 0 .../tests}/__init__.py | 0 .../tests/test_init.py | 18 +++ .../.coverage | Bin 0 -> 278528 bytes .../README.md | 85 ++++++++++++++ .../examples}/cli.py | 0 .../examples}/examples-catalog.json | 0 .../scripts/generate_sam_template.py | 0 .../examples}/src/__init__.py | 0 .../src/block_example/block_example.py | 0 .../src/callback/callback_concurrency.py | 0 .../src/callback/callback_heartbeat.py | 0 .../src/callback/callback_mixed_ops.py | 0 .../examples}/src/callback/callback_serdes.py | 0 .../examples}/src/callback/callback_simple.py | 0 .../src/callback/callback_with_timeout.py | 0 .../comprehensive_operations.py | 0 .../src/handler_error/handler_error.py | 0 .../examples}/src/hello_world.py | 0 .../src/logger_example/logger_example.py | 0 .../examples}/src/map/map_completion.py | 0 .../examples}/src/map/map_operations.py | 0 .../examples}/src/map/map_operations_flat.py | 0 .../src/map/map_with_batch_serdes.py | 0 .../src/map/map_with_custom_serdes.py | 0 .../src/map/map_with_failure_tolerance.py | 0 .../examples}/src/map/map_with_item_namer.py | 0 .../examples}/src/map/map_with_large_scale.py | 0 .../src/map/map_with_max_concurrency.py | 0 .../src/map/map_with_min_successful.py | 0 .../no_replay_execution.py | 0 .../src/none_results/none_results.py | 0 .../examples}/src/parallel/parallel.py | 0 .../src/parallel/parallel_first_successful.py | 0 .../examples}/src/parallel/parallel_flat.py | 0 .../parallel/parallel_with_batch_serdes.py | 0 .../parallel/parallel_with_custom_serdes.py | 0 .../parallel_with_failure_tolerance.py | 0 .../parallel/parallel_with_max_concurrency.py | 0 .../parallel/parallel_with_named_branches.py | 0 .../src/parallel/parallel_with_wait.py | 0 .../run_in_child_context.py | 0 .../run_in_child_context_large_data.py | 0 .../run_in_child_context_step_failure.py | 0 .../src/simple_execution/simple_execution.py | 0 .../examples}/src/step/step.py | 0 .../examples}/src/step/step_no_name.py | 0 .../src/step/step_semantics_at_most_once.py | 0 .../src/step/step_with_exponential_backoff.py | 0 .../examples}/src/step/step_with_name.py | 0 .../examples}/src/step/step_with_retry.py | 0 .../examples}/src/step/steps_with_retry.py | 0 .../examples}/src/wait/multiple_wait.py | 0 .../examples}/src/wait/wait.py | 0 .../examples}/src/wait/wait_with_name.py | 0 .../wait_for_callback/wait_for_callback.py | 0 .../wait_for_callback_anonymous.py | 0 .../wait_for_callback_child.py | 0 .../wait_for_callback_heartbeat.py | 0 .../wait_for_callback_mixed_ops.py | 0 .../wait_for_callback_multiple_invocations.py | 0 .../wait_for_callback_nested.py | 0 .../wait_for_callback_serdes.py | 0 .../wait_for_callback_submitter_failure.py | 0 ...or_callback_submitter_failure_catchable.py | 0 .../wait_for_callback_timeout.py | 0 .../wait_for_condition/wait_for_condition.py | 0 .../examples}/template.yaml | 0 .../examples}/test/README.md | 0 .../examples}/test/__init__.py | 0 .../test/block_example/test_block_example.py | 0 .../callback/test_callback_concurrency.py | 0 .../test/callback/test_callback_heartbeat.py | 0 .../test/callback/test_callback_mixed_ops.py | 0 .../test/callback/test_callback_serdes.py | 0 .../test/callback/test_callback_simple.py | 0 .../test_comprehensive_operations.py | 0 .../examples}/test/conftest.py | 0 .../test/handler_error/test_handler_error.py | 0 .../logger_example/test_logger_example.py | 0 .../examples}/test/map/test_map_completion.py | 0 .../examples}/test/map/test_map_operations.py | 0 .../test/map/test_map_operations_flat.py | 0 .../test/map/test_map_with_batch_serdes.py | 0 .../test/map/test_map_with_custom_serdes.py | 0 .../map/test_map_with_failure_tolerance.py | 0 .../test/map/test_map_with_item_namer.py | 0 .../test/map/test_map_with_large_scale.py | 0 .../test/map/test_map_with_max_concurrency.py | 0 .../test/map/test_map_with_min_successful.py | 0 .../test_no_replay_execution.py | 0 .../test/none_results/test_none_results.py | 0 .../examples}/test/parallel/test_parallel.py | 0 .../test/parallel/test_parallel_flat.py | 0 .../test_parallel_with_batch_serdes.py | 0 .../test_parallel_with_custom_serdes.py | 0 .../test_parallel_with_failure_tolerance.py | 0 .../test_parallel_with_max_concurrency.py | 0 .../test_parallel_with_named_branches.py | 0 .../test/parallel/test_parallel_with_wait.py | 0 .../test_run_in_child_context.py | 0 .../test_run_in_child_context_large_data.py | 0 .../test_run_in_child_context_step_failure.py | 0 .../simple_execution/test_simple_execution.py | 0 .../examples}/test/step/test_step.py | 0 .../test/step/test_step_permutations.py | 0 .../step/test_step_semantics_at_most_once.py | 0 .../test/step/test_step_with_retry.py | 0 .../test/step/test_steps_with_retry.py | 0 .../examples}/test/test_hello_world.py | 0 .../examples}/test/wait/test_multiple_wait.py | 0 .../examples}/test/wait/test_wait.py | 0 .../test/wait/test_wait_permutations.py | 0 .../test_wait_for_callback_anonymous.py | 0 .../test_wait_for_callback_child.py | 0 .../test_wait_for_callback_failure.py | 0 .../test_wait_for_callback_heartbeat.py | 0 .../test_wait_for_callback_mixed_ops.py | 0 ..._wait_for_callback_multiple_invocations.py | 0 .../test_wait_for_callback_nested.py | 0 .../test_wait_for_callback_serdes.py | 0 ...est_wait_for_callback_submitter_failure.py | 0 ...or_callback_submitter_failure_catchable.py | 0 .../test_wait_for_callback_success.py | 0 .../test_wait_for_callback_timeout.py | 0 .../test_wait_for_condition.py | 0 .../pyproject.toml | 0 .../.gitignore | 0 .../__about__.py | 0 .../__init__.py | 0 .../concurrency}/__init__.py | 0 .../concurrency/executor.py | 0 .../concurrency/models.py | 0 .../config.py | 0 .../context.py | 0 .../exceptions.py | 0 .../execution.py | 0 .../identifier.py | 0 .../lambda_service.py | 0 .../logger.py | 0 .../operation/__init__.py | 0 .../operation/base.py | 0 .../operation/callback.py | 0 .../operation/child.py | 0 .../operation/invoke.py | 0 .../operation/map.py | 0 .../operation/parallel.py | 0 .../operation/step.py | 0 .../operation/wait.py | 0 .../operation/wait_for_condition.py | 0 .../aws_durable_execution_sdk_python/py.typed | 0 .../retries.py | 0 .../serdes.py | 0 .../aws_durable_execution_sdk_python/state.py | 0 .../suspend.py | 0 .../threading.py | 0 .../aws_durable_execution_sdk_python/types.py | 0 .../aws_durable_execution_sdk_python/waits.py | 0 .../tests}/__init__.py | 0 .../tests}/concurrency_test.py | 0 .../tests}/config_test.py | 0 .../tests}/context_test.py | 0 ...ble_executions_python_language_sdk_test.py | 0 .../tests/e2e/__init__.py | 0 .../e2e/checkpoint_response_int_test.py | 0 .../tests}/e2e/execution_int_test.py | 0 .../e2e/map_with_concurrent_waits_int_test.py | 0 .../tests}/exceptions_test.py | 0 .../tests}/execution_test.py | 0 .../tests}/lambda_service_test.py | 0 .../tests}/logger_test.py | 0 .../tests/operation/__init__.py | 0 .../tests}/operation/base_test.py | 0 .../tests}/operation/callback_test.py | 0 .../tests}/operation/child_test.py | 0 .../tests}/operation/invoke_test.py | 0 .../tests}/operation/map_test.py | 0 .../tests}/operation/parallel_test.py | 0 .../tests}/operation/step_test.py | 0 .../operation/wait_for_condition_test.py | 0 .../tests}/operation/wait_test.py | 0 .../tests}/retries_test.py | 0 .../tests}/serdes_test.py | 0 .../tests}/state_test.py | 0 .../tests}/suspend_test.py | 0 .../tests}/test_helpers.py | 0 .../tests}/threading_test.py | 0 .../tests}/types_test.py | 0 .../tests}/waits_test.py | 0 202 files changed, 511 insertions(+), 120 deletions(-) delete mode 100644 .github/workflows/sync-package.yml create mode 100644 RELEASING.md create mode 100644 packages/aws-durable-execution-sdk-python-otel/README.md create mode 100644 packages/aws-durable-execution-sdk-python-otel/pyproject.toml create mode 100644 packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__about__.py create mode 100644 packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__init__.py rename src/aws_durable_execution_sdk_python/.gitignore => packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/py.typed (100%) rename {src/aws_durable_execution_sdk_python/concurrency => packages/aws-durable-execution-sdk-python-otel/tests}/__init__.py (100%) create mode 100644 packages/aws-durable-execution-sdk-python-otel/tests/test_init.py create mode 100644 packages/aws-durable-execution-sdk-python/.coverage create mode 100644 packages/aws-durable-execution-sdk-python/README.md rename {examples => packages/aws-durable-execution-sdk-python/examples}/cli.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/examples-catalog.json (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/scripts/generate_sam_template.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/__init__.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/block_example/block_example.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_heartbeat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_mixed_ops.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_simple.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/callback/callback_with_timeout.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/comprehensive_operations/comprehensive_operations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/handler_error/handler_error.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/hello_world.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/logger_example/logger_example.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_completion.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_operations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_operations_flat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_batch_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_custom_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_failure_tolerance.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_item_namer.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_large_scale.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_max_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/map/map_with_min_successful.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/no_replay_execution/no_replay_execution.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/none_results/none_results.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_first_successful.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_flat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_batch_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_custom_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_failure_tolerance.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_max_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_named_branches.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/parallel/parallel_with_wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/run_in_child_context/run_in_child_context.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/run_in_child_context/run_in_child_context_large_data.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/run_in_child_context/run_in_child_context_step_failure.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/simple_execution/simple_execution.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step_no_name.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step_semantics_at_most_once.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step_with_exponential_backoff.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step_with_name.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/step_with_retry.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/step/steps_with_retry.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait/multiple_wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait/wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait/wait_with_name.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_anonymous.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_child.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_heartbeat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_mixed_ops.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_multiple_invocations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_nested.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_submitter_failure.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_callback/wait_for_callback_timeout.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/src/wait_for_condition/wait_for_condition.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/template.yaml (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/README.md (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/__init__.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/block_example/test_block_example.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/callback/test_callback_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/callback/test_callback_heartbeat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/callback/test_callback_mixed_ops.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/callback/test_callback_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/callback/test_callback_simple.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/comprehensive_operations/test_comprehensive_operations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/conftest.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/handler_error/test_handler_error.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/logger_example/test_logger_example.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_completion.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_operations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_operations_flat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_batch_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_custom_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_failure_tolerance.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_item_namer.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_large_scale.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_max_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/map/test_map_with_min_successful.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/no_replay_execution/test_no_replay_execution.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/none_results/test_none_results.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_flat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_batch_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_custom_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_failure_tolerance.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_max_concurrency.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_named_branches.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/parallel/test_parallel_with_wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/run_in_child_context/test_run_in_child_context.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/run_in_child_context/test_run_in_child_context_large_data.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/run_in_child_context/test_run_in_child_context_step_failure.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/simple_execution/test_simple_execution.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/step/test_step.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/step/test_step_permutations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/step/test_step_semantics_at_most_once.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/step/test_step_with_retry.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/step/test_steps_with_retry.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/test_hello_world.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait/test_multiple_wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait/test_wait.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait/test_wait_permutations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_anonymous.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_child.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_failure.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_heartbeat.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_mixed_ops.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_nested.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_serdes.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_submitter_failure.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_success.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_callback/test_wait_for_callback_timeout.py (100%) rename {examples => packages/aws-durable-execution-sdk-python/examples}/test/wait_for_condition/test_wait_for_condition.py (100%) rename pyproject.toml => packages/aws-durable-execution-sdk-python/pyproject.toml (100%) rename tests/__init__.py => packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/.gitignore (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/__about__.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/__init__.py (100%) rename {tests/e2e => packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency}/__init__.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/concurrency/executor.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/concurrency/models.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/config.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/context.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/exceptions.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/execution.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/identifier.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/lambda_service.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/logger.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/__init__.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/base.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/callback.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/child.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/invoke.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/map.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/parallel.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/step.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/wait.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/operation/wait_for_condition.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/py.typed (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/retries.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/serdes.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/state.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/suspend.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/threading.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/types.py (100%) rename {src => packages/aws-durable-execution-sdk-python/src}/aws_durable_execution_sdk_python/waits.py (100%) rename {tests/operation => packages/aws-durable-execution-sdk-python/tests}/__init__.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/concurrency_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/config_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/context_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/durable_executions_python_language_sdk_test.py (100%) create mode 100644 packages/aws-durable-execution-sdk-python/tests/e2e/__init__.py rename {tests => packages/aws-durable-execution-sdk-python/tests}/e2e/checkpoint_response_int_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/e2e/execution_int_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/e2e/map_with_concurrent_waits_int_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/exceptions_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/execution_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/lambda_service_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/logger_test.py (100%) create mode 100644 packages/aws-durable-execution-sdk-python/tests/operation/__init__.py rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/base_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/callback_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/child_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/invoke_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/map_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/parallel_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/step_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/wait_for_condition_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/operation/wait_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/retries_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/serdes_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/state_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/suspend_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/test_helpers.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/threading_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/types_test.py (100%) rename {tests => packages/aws-durable-execution-sdk-python/tests}/waits_test.py (100%) diff --git a/.github/scripts/ci-checks.sh b/.github/scripts/ci-checks.sh index 77f962d8..93ccbeb6 100755 --- a/.github/scripts/ci-checks.sh +++ b/.github/scripts/ci-checks.sh @@ -1,18 +1,37 @@ - #!/bin/sh set -e -hatch run test:cov -echo SUCCESS: tests + coverage +REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" + +PACKAGES=( + "packages/aws-durable-execution-sdk-python" + "packages/aws-durable-execution-sdk-python-otel" +) + +for package_dir in "${PACKAGES[@]}"; do + full_path="$REPO_ROOT/$package_dir" + if [ -d "$full_path" ]; then + echo "==========================================" + echo "Running checks for $package_dir" + echo "==========================================" + cd "$full_path" + + hatch run test:cov + echo "SUCCESS: tests + coverage ($package_dir)" -# type checks -hatch run types:check -echo SUCCESS: typings + # type checks + hatch run types:check + echo "SUCCESS: typings ($package_dir)" -# static analysis -hatch fmt -echo SUCCESS: linting/fmt + # static analysis + hatch fmt + echo "SUCCESS: linting/fmt ($package_dir)" + else + echo "WARNING: $package_dir does not exist, skipping" + fi +done -# commit message validation +# commit message validation (run once from repo root) +cd "$REPO_ROOT" hatch run python .github/scripts/lintcommit.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a89a4c1..2c0b8700 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,10 +43,42 @@ jobs: run: | python -m pip install hatch==1.16.5 - name: static analysis - run: hatch fmt --check + run: | + for pkg in packages/*/; do + if [ -f "$pkg/pyproject.toml" ]; then + echo "=== Checking format: $pkg ===" + cd "$pkg" + hatch fmt --check + cd "$GITHUB_WORKSPACE" + fi + done - name: type checking - run: hatch run types:check + run: | + for pkg in packages/*/; do + if [ -f "$pkg/pyproject.toml" ]; then + echo "=== Type checking: $pkg ===" + cd "$pkg" + hatch run types:check + cd "$GITHUB_WORKSPACE" + fi + done - name: Run tests + coverage - run: hatch run test:cov + run: | + for pkg in packages/*/; do + if [ -f "$pkg/pyproject.toml" ]; then + echo "=== Testing: $pkg ===" + cd "$pkg" + hatch run test:cov + cd "$GITHUB_WORKSPACE" + fi + done - name: Build distribution - run: hatch build + run: | + for pkg in packages/*/; do + if [ -f "$pkg/pyproject.toml" ]; then + echo "=== Building: $pkg ===" + cd "$pkg" + hatch build + cd "$GITHUB_WORKSPACE" + fi + done diff --git a/.github/workflows/deploy-examples.yml b/.github/workflows/deploy-examples.yml index 415ff16c..33223f46 100644 --- a/.github/workflows/deploy-examples.yml +++ b/.github/workflows/deploy-examples.yml @@ -4,8 +4,8 @@ on: pull_request: branches: [ "main", "development"] paths: - - 'src/aws_durable_execution_sdk_python/**' - - 'examples/**' + - 'packages/aws-durable-execution-sdk-python/src/**' + - 'packages/aws-durable-execution-sdk-python/examples/**' - '.github/workflows/deploy-examples.yml' workflow_dispatch: @@ -26,7 +26,7 @@ jobs: - name: Get examples from catalog id: get-examples - working-directory: ./examples + working-directory: ./packages/aws-durable-execution-sdk-python/examples run: | echo "examples=$(jq -c '.examples | map(select(.integration == true))' examples-catalog.json)" >> $GITHUB_OUTPUT @@ -58,10 +58,12 @@ jobs: - name: Install Hatch run: pip install hatch - name: Build examples + working-directory: ./packages/aws-durable-execution-sdk-python run: hatch run examples:build - name: Deploy Lambda function - ${{ matrix.example.name }} id: deploy + working-directory: ./packages/aws-durable-execution-sdk-python env: AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} LAMBDA_ENDPOINT: "https://lambda.us-west-2.amazonaws.com" @@ -99,6 +101,7 @@ jobs: echo "QUALIFIED_FUNCTION_NAME=$QUALIFIED_FUNCTION_NAME" >> $GITHUB_OUTPUT - name: Run Integration Tests - ${{ matrix.example.name }} + working-directory: ./packages/aws-durable-execution-sdk-python env: AWS_REGION: ${{ env.AWS_REGION }} LAMBDA_ENDPOINT: "https://lambda.us-west-2.amazonaws.com" diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 13441abc..7a8b011a 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -37,11 +37,11 @@ jobs: run: python -m pip install hatch==1.16.5 - name: Setup and run tests - working-directory: language-sdk + working-directory: language-sdk/packages/aws-durable-execution-sdk-python run: | echo "Running SDK tests..." - hatch run -- test:pip install -e ../testing-sdk - hatch run -- test:pip install -e ../language-sdk + hatch run -- test:pip install -e ../../../testing-sdk + hatch run -- test:pip install -e . hatch fmt --check hatch run types:check hatch run test:cov @@ -84,7 +84,7 @@ jobs: - name: Get integration examples id: get-examples - working-directory: language-sdk/examples + working-directory: language-sdk/packages/aws-durable-execution-sdk-python/examples run: | echo "examples=$(jq -c '.examples | map(select(.integration == true)) | .[0:2]' examples-catalog.json)" >> $GITHUB_OUTPUT @@ -97,7 +97,7 @@ jobs: rm -rf /tmp/aws/ - name: Deploy and test examples - working-directory: language-sdk + working-directory: language-sdk/packages/aws-durable-execution-sdk-python env: AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} LAMBDA_ENDPOINT: "https://lambda.us-west-2.amazonaws.com" @@ -105,7 +105,7 @@ jobs: KMS_KEY_ARN: ${{ secrets.KMS_KEY_ARN }} run: | echo "Building examples..." - hatch run -- examples:pip install -e ../testing-sdk + hatch run -- examples:pip install -e ../../../testing-sdk hatch run examples:build # Get first integration example for testing diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml index e0e0a2b6..726f823b 100644 --- a/.github/workflows/pypi-publish.yml +++ b/.github/workflows/pypi-publish.yml @@ -1,4 +1,4 @@ -# This workflow will upload a Python Package to PyPI when a release is created +# This workflow will upload Python Packages to PyPI when a release is created # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries # This workflow uses actions that are not certified by GitHub. @@ -18,6 +18,14 @@ permissions: jobs: release-build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + package: + - name: aws-durable-execution-sdk-python + path: packages/aws-durable-execution-sdk-python + - name: aws-durable-execution-sdk-python-otel + path: packages/aws-durable-execution-sdk-python-otel steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -25,52 +33,51 @@ jobs: - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.11" - - name: Install Hatch - run: | - python -m pip install --upgrade hatch==1.16.5 + + - name: Install Hatch + run: python -m pip install --upgrade hatch==1.16.5 + - name: Build release distributions - run: | - # NOTE: put your own distribution build steps here. - hatch build + working-directory: ${{ matrix.package.path }} + run: hatch build - name: Upload distributions uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: release-dists - path: dist/ + name: release-dists-${{ matrix.package.name }} + path: ${{ matrix.package.path }}/dist/ pypi-publish: runs-on: ubuntu-latest needs: - release-build + strategy: + fail-fast: false + matrix: + package: + - name: aws-durable-execution-sdk-python + - name: aws-durable-execution-sdk-python-otel permissions: - # IMPORTANT: this permission is mandatory for trusted publishing id-token: write - # Dedicated environments with protections for publishing are strongly recommended. - # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules environment: name: pypi - # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status: - # url: https://pypi.org/p/aws-durable-execution-sdk-python - # - # ALTERNATIVE: if your GitHub Release name is the PyPI project version string - # ALTERNATIVE: exactly, uncomment the following line instead: - url: https://pypi.org/project/aws-durable-execution-sdk-python/${{ github.event.release.name }} + url: https://pypi.org/project/${{ matrix.package.name }}/${{ github.event.release.name }} steps: - name: Retrieve release distributions uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: release-dists + name: release-dists-${{ matrix.package.name }} path: dist/ - - name: Publish release distributions to PyPI + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: packages-dir: dist/ notify-release: + if: always() && contains(needs.pypi-publish.result, 'success') needs: [pypi-publish] uses: ./.github/workflows/notify-release.yml with: diff --git a/.github/workflows/sync-package.yml b/.github/workflows/sync-package.yml deleted file mode 100644 index afe31965..00000000 --- a/.github/workflows/sync-package.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Sync package - -on: - push: - branches: [ "main" ] -env: - AWS_REGION : "us-west-2" - -# permission can be added at job level or workflow level -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout - -jobs: - on-success: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.13"] - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ matrix.python-version }} - - name: Install Hatch - run: | - python -m pip install --upgrade hatch==1.16.5 - - name: Build distribution - run: hatch build - - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 - with: - role-to-assume: "${{ secrets.ACTIONS_SYNC_ROLE_NAME }}" - role-session-name: gh-python - aws-region: ${{ env.AWS_REGION }} - - name: Copy tar gz build file to s3 - run: | - aws s3 cp ./dist/*.tar.gz \ - s3://${{ secrets.S3_BUCKET_NAME }}/aws-durable-execution-sdk-python.tar.gz - - name: commit tar gz to Gitfarm - run: | - aws lambda invoke \ - --function-name ${{ secrets.SYNC_LAMBDA_ARN }} \ - --payload '{"gitFarmRepo":"${{ secrets.GITFARM_LAN_SDK_REPO }}","gitFarmBranch":"${{ secrets.GITFARM_LAN_SDK_BRANCH }}","gitFarmFilepath":"aws-durable-execution-sdk-python.tar.gz","s3Bucket":"${{ secrets.S3_BUCKET_NAME }}","s3FilePath":"aws-durable-execution-sdk-python.tar.gz", "gitHubRepo": "aws-durable-execution-sdk-python", "gitHubCommit":"${{ github.sha }}"}' \ - --cli-binary-format raw-in-base64-out \ - output.txt - - name: Check for error in lambda invoke - run: | - if grep -q "Error" output.txt; then - cat output.txt - exit 1 - fi - - name: Copy whl build file to s3 - run: | - aws s3 cp ./dist/*.whl \ - s3://${{ secrets.S3_BUCKET_NAME }}/aws-durable-execution-sdk-python.whl - - name: commit whl to Gitfarm - run: | - aws lambda invoke \ - --function-name ${{ secrets.SYNC_LAMBDA_ARN }} \ - --payload '{"gitFarmRepo":"${{ secrets.GITFARM_LAN_SDK_REPO }}","gitFarmBranch":"${{ secrets.GITFARM_LAN_SDK_BRANCH }}","gitFarmFilepath":"aws-durable-execution-sdk-python.whl","s3Bucket":"${{ secrets.S3_BUCKET_NAME }}","s3FilePath":"aws-durable-execution-sdk-python.whl", "gitHubRepo": "aws-durable-execution-sdk-python", "gitHubCommit":"${{ github.sha }}"}' \ - --cli-binary-format raw-in-base64-out \ - output.txt - - name: Check for error in lambda invoke - run: | - if grep -q "Error" output.txt; then - cat output.txt - exit 1 - fi diff --git a/.gitignore b/.gitignore index bfc52e93..fa41c3e0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ *$py.class *.egg-info/ +*.coverage /.coverage /.coverage.* /.cache @@ -30,7 +31,7 @@ dist/ .kiro/ -/examples/build/* -/examples/*.zip +examples/build/* +examples/*.zip .env \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a65b26a..880f3676 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,35 @@ information to effectively respond to your bug report or contribution. ## Dependencies Install [hatch](https://hatch.pypa.io/dev/install/). +## Repository Structure + +This is a monorepo containing multiple packages under the `packages/` directory: + +``` +packages/ +├── aws-durable-execution-sdk-python/ # Core SDK +│ ├── pyproject.toml +│ ├── src/ +│ ├── tests/ +│ └── examples/ +└── aws-durable-execution-sdk-python-otel/ # OpenTelemetry instrumentation + ├── pyproject.toml + ├── src/ + └── tests/ +``` + +Shared files (`.github/`, `LICENSE`, `CONTRIBUTING.md`, etc.) live at the repository root. + ## Developer workflow + +All `hatch` commands must be run from within a specific package directory: + +```bash +cd packages/aws-durable-execution-sdk-python +# or +cd packages/aws-durable-execution-sdk-python-otel +``` + These are all the checks you would typically do as you prepare a PR: ``` # just test @@ -25,7 +53,7 @@ hatch run types:check hatch fmt ``` -There is a convenience script for the above that you can run from the root of the repo as you prepare your PR: +There is a convenience script that runs checks across all packages from the root of the repo: ``` .github/scripts/ci-checks.sh ``` @@ -131,7 +159,8 @@ class WaitOptions: ## Set up your IDE Point your IDE at the hatch virtual environment to have it recognize dependencies -and imports. +and imports. Run these commands from within the package directory you're working on +(e.g., `packages/aws-durable-execution-sdk-python`). You can find the path to the hatch Python interpreter like this: ``` @@ -148,6 +177,7 @@ errors finding the interpreter. You can create a local .venv file symlink _witho in the path: ```bash +# From within the package directory, e.g. packages/aws-durable-execution-sdk-python # create a symlink at: ./.venv/bin/python rm -rf .venv && ln -s "$(hatch env find)" .venv ``` @@ -179,6 +209,8 @@ These `settings.json` settings are useful: ## Testing ### How to run tests +Run these commands from within a package directory (e.g., `packages/aws-durable-execution-sdk-python`). + To run all tests: ``` hatch test @@ -220,7 +252,8 @@ tests/mypackage/mymodule_test.py ## Examples and Deployment -The project includes a unified CLI tool for managing examples, deployment, and AWS account setup: +The project includes a unified CLI tool for managing examples, deployment, and AWS account setup. +Run these commands from the core SDK package directory (`packages/aws-durable-execution-sdk-python`): ### Bootstrap AWS Account ```bash diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..3b5b8264 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,106 @@ +# Releasing + +This document describes how to cut a release for packages in this monorepo and how the automated PyPI publishing workflow is triggered. + +## Packages + +This monorepo contains the following packages: + +| Package | Path | Tag Prefix | +|---------|------|------------| +| `aws-durable-execution-sdk-python` | `packages/aws-durable-execution-sdk-python` | `sdk` | +| `aws-durable-execution-sdk-python-otel` | `packages/aws-durable-execution-sdk-python-otel` | `otel` | + +## Versioning + +Each package maintains its own version in its respective `__about__.py` file: + +- SDK: `packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/__about__.py` +- OTel: `packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__about__.py` + +Bump the version in the appropriate `__about__.py` file(s) and merge to `main` before creating a release. + +## Cutting a Release + +### 1. Bump the version + +Update the `__version__` string in the relevant `__about__.py` file(s). Commit and merge to `main`. + +### 2. Create a GitHub Release + +1. Go to the [Releases page](https://github.com/aws/aws-durable-execution-sdk-python/releases) on GitHub. +2. Click **Draft a new release**. +3. Create a new tag following the tagging convention below. +4. Set the release title (typically the same as the tag). +5. Write release notes following the format described in [Release Notes Format](#release-notes-format). +6. Click **Publish release**. + +### Tagging Convention + +The tag should be the version of the package being bumped, prepended with a descriptive prefix: + +- **SDK only:** `sdk-v` (e.g., `sdk-v1.6.0`) +- **OTel only:** `otel-v` (e.g., `otel-v0.3.0`) +- **Both packages in a single release:** comma-separate the sub-tags (e.g., `sdk-1.6.0,otel-0.3.0`) + +Examples: + +``` +sdk-1.6.0 +otel-0.3.0 +sdk-1.6.0,otel-0.3.0 +``` + +If additional packages are added to the monorepo in the future, follow the same pattern: choose a short descriptive prefix for the package and use `-`. + +## How Publishing Works + +Creating a GitHub Release triggers the [`pypi-publish.yml`](.github/workflows/pypi-publish.yml) workflow automatically. The workflow: + +1. **Builds** both packages using [Hatch](https://hatch.pypa.io/) (`hatch build`). +2. **Uploads** the built distributions as artifacts. +3. **Publishes** each package to [PyPI](https://pypi.org/) using trusted publishing (OIDC-based, no API tokens required). + +The workflow runs on the `release: [published]` event, so it fires whenever a release is published on GitHub — no manual intervention is needed beyond creating the release. + +> **Note:** The workflow builds and publishes all packages in the matrix. Ensure the version in each package's `__about__.py` is correct before publishing. If only one package has a version bump, PyPI will reject the re-upload of the unchanged package (which is expected and harmless since `fail-fast: false` is set). + +## Release Notes Format + +Release notes should maintain separate timelines for each package. Use the following structure: + +```markdown +## aws-durable-execution-sdk-python v1.6.0 + +### Features +- Added support for X +- New `context.foo()` API + +### Bug Fixes +- Fixed issue with Y under Z conditions + +### Breaking Changes +- Removed deprecated `bar()` method + +--- + +## aws-durable-execution-sdk-python-otel v0.3.0 + +### Features +- Added tracing for `map` operations + +### Bug Fixes +- Fixed span context propagation in child contexts +``` + +If only one package is being released, include only that package's section. Each package's changelog should be self-contained so users can follow the history of the package they depend on independently. + +## Checklist + +Before publishing a release: + +- [ ] Version bumped in the relevant `__about__.py` file(s) +- [ ] Changes merged to `main` +- [ ] CI checks pass on `main` +- [ ] Release notes written with separate sections per package +- [ ] Tag follows the naming convention (`sdk-X.Y.Z`, `otel-X.Y.Z`, or comma-separated) diff --git a/packages/aws-durable-execution-sdk-python-otel/README.md b/packages/aws-durable-execution-sdk-python-otel/README.md new file mode 100644 index 00000000..b69c4b51 --- /dev/null +++ b/packages/aws-durable-execution-sdk-python-otel/README.md @@ -0,0 +1,47 @@ +# aws-durable-execution-sdk-python-otel + +OpenTelemetry instrumentation for the [AWS Durable Execution SDK for Python](https://github.com/aws/aws-durable-execution-sdk-python). + +## Overview + +This package provides automatic OpenTelemetry tracing for durable execution workflows, giving you visibility into step execution, waits, retries, and overall workflow performance. + +## Installation + +```bash +pip install aws-durable-execution-sdk-python-otel +``` + +## Quick Start + +```python +from aws_durable_execution_sdk_python import DurableContext, durable_execution +from aws_durable_execution_sdk_python_otel import instrument_durable_execution + +# Instrument the SDK (call once at module load) +instrument_durable_execution() + +@durable_execution +def handler(event: dict, context: DurableContext) -> dict: + # Steps, waits, and invokes are automatically traced + result = context.step(lambda _: do_work(), name="my-step") + return {"result": result} +``` + +## Features + +- Automatic span creation for steps, waits, invokes, and child contexts +- Replay-aware tracing (distinguishes fresh executions from replays) +- Error recording with proper OTel status codes +- Configurable span attributes and naming + +## Requirements + +- Python >= 3.11 +- `aws-durable-execution-sdk-python` >= 1.5.0 +- `opentelemetry-api` >= 1.20.0 +- `opentelemetry-sdk` >= 1.20.0 + +## License + +Apache-2.0 diff --git a/packages/aws-durable-execution-sdk-python-otel/pyproject.toml b/packages/aws-durable-execution-sdk-python-otel/pyproject.toml new file mode 100644 index 00000000..998db75f --- /dev/null +++ b/packages/aws-durable-execution-sdk-python-otel/pyproject.toml @@ -0,0 +1,100 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "aws-durable-execution-sdk-python-otel" +dynamic = ["version"] +description = 'OpenTelemetry instrumentation for AWS Durable Execution SDK for Python' +readme = "README.md" +requires-python = ">=3.11" +license = "Apache-2.0" +keywords = ["opentelemetry", "tracing", "observability", "durable-execution"] +authors = [{ name = "AWS durable-execution-dev", email = "durable-execution-dev@amazon.com" }] +classifiers = [ + "Development Status :: 4 - Beta", + "Programming Language :: Python", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dependencies = [ + "aws-durable-execution-sdk-python>=1.5.0", + "opentelemetry-api>=1.20.0", + "opentelemetry-sdk>=1.20.0", +] + +[project.urls] +Documentation = "https://github.com/aws/aws-durable-execution-sdk-python#readme" +Issues = "https://github.com/aws/aws-durable-execution-sdk-python/issues" +Source = "https://github.com/aws/aws-durable-execution-sdk-python" + +[tool.hatch.build.targets.wheel] +packages = ["src/aws_durable_execution_sdk_python_otel"] + +[tool.hatch.version] +path = "src/aws_durable_execution_sdk_python_otel/__about__.py" + +[tool.hatch.envs.test] +dependencies = [ + "coverage[toml]", + "pytest", + "pytest-cov", + "opentelemetry-sdk>=1.20.0", +] + +[tool.hatch.envs.test.scripts] +cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=src/aws_durable_execution_sdk_python_otel" + +[tool.hatch.envs.types] +extra-dependencies = ["mypy>=1.0.0", "pytest"] + +[tool.hatch.envs.types.scripts] +check = "mypy --install-types --non-interactive {args:src/aws_durable_execution_sdk_python_otel tests}" + +[tool.coverage.run] +source_pkgs = ["aws_durable_execution_sdk_python_otel"] +branch = true +parallel = true +omit = ["src/aws_durable_execution_sdk_python_otel/__about__.py"] + +[tool.coverage.paths] +aws_durable_execution_sdk_python_otel = [ + "src/aws_durable_execution_sdk_python_otel", + "*/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel", +] + +[tool.coverage.report] +exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"] + +[tool.ruff] +line-length = 88 +target-version = "py311" + +[tool.ruff.lint] +preview = true +select = ["TID252"] + +[tool.ruff.lint.isort] +known-first-party = ["aws_durable_execution_sdk_python_otel"] +force-single-line = false +lines-after-imports = 2 + +[tool.ruff.lint.per-file-ignores] +"tests/**" = [ + "ARG001", + "ARG002", + "ARG005", + "S101", + "PLR2004", + "PLR6301", + "SIM117", + "TRY301", +] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-v --strict-markers" diff --git a/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__about__.py b/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__about__.py new file mode 100644 index 00000000..1c35361c --- /dev/null +++ b/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__about__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2025-present Amazon.com, Inc. or its affiliates. +# +# SPDX-License-Identifier: Apache-2.0 +__version__ = "0.1.0" diff --git a/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__init__.py b/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__init__.py new file mode 100644 index 00000000..63b1b9cc --- /dev/null +++ b/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/__init__.py @@ -0,0 +1,8 @@ +"""OpenTelemetry instrumentation for AWS Lambda Durable Executions Python SDK.""" + +from aws_durable_execution_sdk_python_otel.__about__ import __version__ + + +__all__ = [ + "__version__", +] diff --git a/src/aws_durable_execution_sdk_python/.gitignore b/packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/py.typed similarity index 100% rename from src/aws_durable_execution_sdk_python/.gitignore rename to packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/py.typed diff --git a/src/aws_durable_execution_sdk_python/concurrency/__init__.py b/packages/aws-durable-execution-sdk-python-otel/tests/__init__.py similarity index 100% rename from src/aws_durable_execution_sdk_python/concurrency/__init__.py rename to packages/aws-durable-execution-sdk-python-otel/tests/__init__.py diff --git a/packages/aws-durable-execution-sdk-python-otel/tests/test_init.py b/packages/aws-durable-execution-sdk-python-otel/tests/test_init.py new file mode 100644 index 00000000..4144ba82 --- /dev/null +++ b/packages/aws-durable-execution-sdk-python-otel/tests/test_init.py @@ -0,0 +1,18 @@ +"""Tests for aws_durable_execution_sdk_python_otel package.""" + +from aws_durable_execution_sdk_python_otel import __version__ + + +def test_version_is_set(): + """Verify the package version is defined.""" + assert __version__ is not None + assert isinstance(__version__, str) + assert len(__version__) > 0 + + +def test_version_format(): + """Verify the package version follows semver format.""" + parts = __version__.split(".") + assert len(parts) == 3 + for part in parts: + assert part.isdigit() diff --git a/packages/aws-durable-execution-sdk-python/.coverage b/packages/aws-durable-execution-sdk-python/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..ccb4aa7455993d6e3dd07b717a579fe87f161b6b GIT binary patch literal 278528 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ʥc4_Sb>;Rlz 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 literal 0 HcmV?d00001 diff --git a/packages/aws-durable-execution-sdk-python/README.md b/packages/aws-durable-execution-sdk-python/README.md new file mode 100644 index 00000000..3a772717 --- /dev/null +++ b/packages/aws-durable-execution-sdk-python/README.md @@ -0,0 +1,85 @@ +# AWS Durable Execution SDK for Python + +[![Build](https://github.com/aws/aws-durable-execution-sdk-python/actions/workflows/ci.yml/badge.svg)](https://github.com/aws/aws-durable-execution-sdk-python/actions/workflows/ci.yml) +[![PyPI - Version](https://img.shields.io/pypi/v/aws-durable-execution-sdk-python.svg)](https://pypi.org/project/aws-durable-execution-sdk-python) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aws-durable-execution-sdk-python.svg)](https://pypi.org/project/aws-durable-execution-sdk-python) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aws/aws-durable-execution-sdk-python/badge)](https://scorecard.dev/viewer/?uri=github.com/aws/aws-durable-execution-sdk-python) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) + +----- + +Build reliable, long-running AWS Lambda workflows with checkpointed steps, waits, callbacks, and parallel execution. + +## ✨ Key Features + +- **Automatic checkpointing** - Resume execution after Lambda pauses or restarts +- **Durable steps** - Run work with retry strategies and deterministic replay +- **Waits and callbacks** - Pause for time or external signals without blocking Lambda +- **Parallel and map operations** - Fan out work with configurable completion criteria +- **Child contexts** - Structure complex workflows into isolated subflows +- **Replay-safe logging** - Use `context.logger` for structured, de-duplicated logs +- **Local and cloud testing** - Validate workflows with the testing SDK + +## 📦 Packages + +| Package | Description | Version | +| --- | --- | --- | +| `aws-durable-execution-sdk-python` | Execution SDK for Lambda durable functions | [![PyPI - Version](https://img.shields.io/pypi/v/aws-durable-execution-sdk-python.svg)](https://pypi.org/project/aws-durable-execution-sdk-python) | +| `aws-durable-execution-sdk-python-testing` | Local/cloud test runner and pytest helpers | [![PyPI - Version](https://img.shields.io/pypi/v/aws-durable-execution-sdk-python-testing.svg)](https://pypi.org/project/aws-durable-execution-sdk-python-testing) | + +## 🚀 Quick Start + +Install the execution SDK: + +```console +pip install aws-durable-execution-sdk-python +``` + +Create a durable Lambda handler: + +```python +from aws_durable_execution_sdk_python import ( + DurableContext, + StepContext, + durable_execution, + durable_step, +) +from aws_durable_execution_sdk_python.config import Duration + +@durable_step +def validate_order(step_ctx: StepContext, order_id: str) -> dict: + step_ctx.logger.info("Validating order", extra={"order_id": order_id}) + return {"order_id": order_id, "valid": True} + +@durable_execution +def handler(event: dict, context: DurableContext) -> dict: + order_id = event["order_id"] + context.logger.info("Starting workflow", extra={"order_id": order_id}) + + validation = context.step(validate_order(order_id), name="validate_order") + if not validation["valid"]: + return {"status": "rejected", "order_id": order_id} + + # simulate approval (real world: use wait_for_callback) + context.wait(duration=Duration.from_seconds(5), name="await_confirmation") + + return {"status": "approved", "order_id": order_id} +``` + +## 📚 Documentation + +The complete documentation for the AWS Durable Execution SDK for Python lives on the AWS Documentation site: + +- **[AWS Durable Execution Documentation](https://docs.aws.amazon.com/durable-execution/)** - Concepts, getting started, core operations, advanced topics, and API reference +- **[AWS Lambda Durable Functions Guide](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)** - How durable functions work on Lambda + +## 💬 Feedback & Support + +- [Bug report](https://github.com/aws/aws-durable-execution-sdk-python/issues/new?template=bug_report.yml) +- [Feature request](https://github.com/aws/aws-durable-execution-sdk-python/issues/new?template=feature_request.yml) +- [Documentation feedback](https://github.com/aws/aws-durable-execution-sdk-python/issues/new?template=documentation.yml) +- [Contributing guide](CONTRIBUTING.md) + +## 📄 License + +See the [LICENSE](LICENSE) file for our project's licensing. diff --git a/examples/cli.py b/packages/aws-durable-execution-sdk-python/examples/cli.py similarity index 100% rename from examples/cli.py rename to packages/aws-durable-execution-sdk-python/examples/cli.py diff --git a/examples/examples-catalog.json b/packages/aws-durable-execution-sdk-python/examples/examples-catalog.json similarity index 100% rename from examples/examples-catalog.json rename to packages/aws-durable-execution-sdk-python/examples/examples-catalog.json diff --git a/examples/scripts/generate_sam_template.py b/packages/aws-durable-execution-sdk-python/examples/scripts/generate_sam_template.py similarity index 100% rename from examples/scripts/generate_sam_template.py rename to packages/aws-durable-execution-sdk-python/examples/scripts/generate_sam_template.py diff --git a/examples/src/__init__.py b/packages/aws-durable-execution-sdk-python/examples/src/__init__.py similarity index 100% rename from examples/src/__init__.py rename to packages/aws-durable-execution-sdk-python/examples/src/__init__.py diff --git a/examples/src/block_example/block_example.py b/packages/aws-durable-execution-sdk-python/examples/src/block_example/block_example.py similarity index 100% rename from examples/src/block_example/block_example.py rename to packages/aws-durable-execution-sdk-python/examples/src/block_example/block_example.py diff --git a/examples/src/callback/callback_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_concurrency.py similarity index 100% rename from examples/src/callback/callback_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_concurrency.py diff --git a/examples/src/callback/callback_heartbeat.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_heartbeat.py similarity index 100% rename from examples/src/callback/callback_heartbeat.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_heartbeat.py diff --git a/examples/src/callback/callback_mixed_ops.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_mixed_ops.py similarity index 100% rename from examples/src/callback/callback_mixed_ops.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_mixed_ops.py diff --git a/examples/src/callback/callback_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_serdes.py similarity index 100% rename from examples/src/callback/callback_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_serdes.py diff --git a/examples/src/callback/callback_simple.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_simple.py similarity index 100% rename from examples/src/callback/callback_simple.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_simple.py diff --git a/examples/src/callback/callback_with_timeout.py b/packages/aws-durable-execution-sdk-python/examples/src/callback/callback_with_timeout.py similarity index 100% rename from examples/src/callback/callback_with_timeout.py rename to packages/aws-durable-execution-sdk-python/examples/src/callback/callback_with_timeout.py diff --git a/examples/src/comprehensive_operations/comprehensive_operations.py b/packages/aws-durable-execution-sdk-python/examples/src/comprehensive_operations/comprehensive_operations.py similarity index 100% rename from examples/src/comprehensive_operations/comprehensive_operations.py rename to packages/aws-durable-execution-sdk-python/examples/src/comprehensive_operations/comprehensive_operations.py diff --git a/examples/src/handler_error/handler_error.py b/packages/aws-durable-execution-sdk-python/examples/src/handler_error/handler_error.py similarity index 100% rename from examples/src/handler_error/handler_error.py rename to packages/aws-durable-execution-sdk-python/examples/src/handler_error/handler_error.py diff --git a/examples/src/hello_world.py b/packages/aws-durable-execution-sdk-python/examples/src/hello_world.py similarity index 100% rename from examples/src/hello_world.py rename to packages/aws-durable-execution-sdk-python/examples/src/hello_world.py diff --git a/examples/src/logger_example/logger_example.py b/packages/aws-durable-execution-sdk-python/examples/src/logger_example/logger_example.py similarity index 100% rename from examples/src/logger_example/logger_example.py rename to packages/aws-durable-execution-sdk-python/examples/src/logger_example/logger_example.py diff --git a/examples/src/map/map_completion.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_completion.py similarity index 100% rename from examples/src/map/map_completion.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_completion.py diff --git a/examples/src/map/map_operations.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_operations.py similarity index 100% rename from examples/src/map/map_operations.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_operations.py diff --git a/examples/src/map/map_operations_flat.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_operations_flat.py similarity index 100% rename from examples/src/map/map_operations_flat.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_operations_flat.py diff --git a/examples/src/map/map_with_batch_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_batch_serdes.py similarity index 100% rename from examples/src/map/map_with_batch_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_batch_serdes.py diff --git a/examples/src/map/map_with_custom_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_custom_serdes.py similarity index 100% rename from examples/src/map/map_with_custom_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_custom_serdes.py diff --git a/examples/src/map/map_with_failure_tolerance.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_failure_tolerance.py similarity index 100% rename from examples/src/map/map_with_failure_tolerance.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_failure_tolerance.py diff --git a/examples/src/map/map_with_item_namer.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_item_namer.py similarity index 100% rename from examples/src/map/map_with_item_namer.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_item_namer.py diff --git a/examples/src/map/map_with_large_scale.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_large_scale.py similarity index 100% rename from examples/src/map/map_with_large_scale.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_large_scale.py diff --git a/examples/src/map/map_with_max_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_max_concurrency.py similarity index 100% rename from examples/src/map/map_with_max_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_max_concurrency.py diff --git a/examples/src/map/map_with_min_successful.py b/packages/aws-durable-execution-sdk-python/examples/src/map/map_with_min_successful.py similarity index 100% rename from examples/src/map/map_with_min_successful.py rename to packages/aws-durable-execution-sdk-python/examples/src/map/map_with_min_successful.py diff --git a/examples/src/no_replay_execution/no_replay_execution.py b/packages/aws-durable-execution-sdk-python/examples/src/no_replay_execution/no_replay_execution.py similarity index 100% rename from examples/src/no_replay_execution/no_replay_execution.py rename to packages/aws-durable-execution-sdk-python/examples/src/no_replay_execution/no_replay_execution.py diff --git a/examples/src/none_results/none_results.py b/packages/aws-durable-execution-sdk-python/examples/src/none_results/none_results.py similarity index 100% rename from examples/src/none_results/none_results.py rename to packages/aws-durable-execution-sdk-python/examples/src/none_results/none_results.py diff --git a/examples/src/parallel/parallel.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel.py similarity index 100% rename from examples/src/parallel/parallel.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel.py diff --git a/examples/src/parallel/parallel_first_successful.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_first_successful.py similarity index 100% rename from examples/src/parallel/parallel_first_successful.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_first_successful.py diff --git a/examples/src/parallel/parallel_flat.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_flat.py similarity index 100% rename from examples/src/parallel/parallel_flat.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_flat.py diff --git a/examples/src/parallel/parallel_with_batch_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_batch_serdes.py similarity index 100% rename from examples/src/parallel/parallel_with_batch_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_batch_serdes.py diff --git a/examples/src/parallel/parallel_with_custom_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_custom_serdes.py similarity index 100% rename from examples/src/parallel/parallel_with_custom_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_custom_serdes.py diff --git a/examples/src/parallel/parallel_with_failure_tolerance.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_failure_tolerance.py similarity index 100% rename from examples/src/parallel/parallel_with_failure_tolerance.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_failure_tolerance.py diff --git a/examples/src/parallel/parallel_with_max_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_max_concurrency.py similarity index 100% rename from examples/src/parallel/parallel_with_max_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_max_concurrency.py diff --git a/examples/src/parallel/parallel_with_named_branches.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_named_branches.py similarity index 100% rename from examples/src/parallel/parallel_with_named_branches.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_named_branches.py diff --git a/examples/src/parallel/parallel_with_wait.py b/packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_wait.py similarity index 100% rename from examples/src/parallel/parallel_with_wait.py rename to packages/aws-durable-execution-sdk-python/examples/src/parallel/parallel_with_wait.py diff --git a/examples/src/run_in_child_context/run_in_child_context.py b/packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context.py similarity index 100% rename from examples/src/run_in_child_context/run_in_child_context.py rename to packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context.py diff --git a/examples/src/run_in_child_context/run_in_child_context_large_data.py b/packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context_large_data.py similarity index 100% rename from examples/src/run_in_child_context/run_in_child_context_large_data.py rename to packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context_large_data.py diff --git a/examples/src/run_in_child_context/run_in_child_context_step_failure.py b/packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context_step_failure.py similarity index 100% rename from examples/src/run_in_child_context/run_in_child_context_step_failure.py rename to packages/aws-durable-execution-sdk-python/examples/src/run_in_child_context/run_in_child_context_step_failure.py diff --git a/examples/src/simple_execution/simple_execution.py b/packages/aws-durable-execution-sdk-python/examples/src/simple_execution/simple_execution.py similarity index 100% rename from examples/src/simple_execution/simple_execution.py rename to packages/aws-durable-execution-sdk-python/examples/src/simple_execution/simple_execution.py diff --git a/examples/src/step/step.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step.py similarity index 100% rename from examples/src/step/step.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step.py diff --git a/examples/src/step/step_no_name.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step_no_name.py similarity index 100% rename from examples/src/step/step_no_name.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step_no_name.py diff --git a/examples/src/step/step_semantics_at_most_once.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step_semantics_at_most_once.py similarity index 100% rename from examples/src/step/step_semantics_at_most_once.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step_semantics_at_most_once.py diff --git a/examples/src/step/step_with_exponential_backoff.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step_with_exponential_backoff.py similarity index 100% rename from examples/src/step/step_with_exponential_backoff.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step_with_exponential_backoff.py diff --git a/examples/src/step/step_with_name.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step_with_name.py similarity index 100% rename from examples/src/step/step_with_name.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step_with_name.py diff --git a/examples/src/step/step_with_retry.py b/packages/aws-durable-execution-sdk-python/examples/src/step/step_with_retry.py similarity index 100% rename from examples/src/step/step_with_retry.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/step_with_retry.py diff --git a/examples/src/step/steps_with_retry.py b/packages/aws-durable-execution-sdk-python/examples/src/step/steps_with_retry.py similarity index 100% rename from examples/src/step/steps_with_retry.py rename to packages/aws-durable-execution-sdk-python/examples/src/step/steps_with_retry.py diff --git a/examples/src/wait/multiple_wait.py b/packages/aws-durable-execution-sdk-python/examples/src/wait/multiple_wait.py similarity index 100% rename from examples/src/wait/multiple_wait.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait/multiple_wait.py diff --git a/examples/src/wait/wait.py b/packages/aws-durable-execution-sdk-python/examples/src/wait/wait.py similarity index 100% rename from examples/src/wait/wait.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait/wait.py diff --git a/examples/src/wait/wait_with_name.py b/packages/aws-durable-execution-sdk-python/examples/src/wait/wait_with_name.py similarity index 100% rename from examples/src/wait/wait_with_name.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait/wait_with_name.py diff --git a/examples/src/wait_for_callback/wait_for_callback.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback.py diff --git a/examples/src/wait_for_callback/wait_for_callback_anonymous.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_anonymous.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_anonymous.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_anonymous.py diff --git a/examples/src/wait_for_callback/wait_for_callback_child.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_child.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_child.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_child.py diff --git a/examples/src/wait_for_callback/wait_for_callback_heartbeat.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_heartbeat.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_heartbeat.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_heartbeat.py diff --git a/examples/src/wait_for_callback/wait_for_callback_mixed_ops.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_mixed_ops.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_mixed_ops.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_mixed_ops.py diff --git a/examples/src/wait_for_callback/wait_for_callback_multiple_invocations.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_multiple_invocations.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_multiple_invocations.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_multiple_invocations.py diff --git a/examples/src/wait_for_callback/wait_for_callback_nested.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_nested.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_nested.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_nested.py diff --git a/examples/src/wait_for_callback/wait_for_callback_serdes.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_serdes.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_serdes.py diff --git a/examples/src/wait_for_callback/wait_for_callback_submitter_failure.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_submitter_failure.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_submitter_failure.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_submitter_failure.py diff --git a/examples/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_submitter_failure_catchable.py diff --git a/examples/src/wait_for_callback/wait_for_callback_timeout.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_timeout.py similarity index 100% rename from examples/src/wait_for_callback/wait_for_callback_timeout.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_callback/wait_for_callback_timeout.py diff --git a/examples/src/wait_for_condition/wait_for_condition.py b/packages/aws-durable-execution-sdk-python/examples/src/wait_for_condition/wait_for_condition.py similarity index 100% rename from examples/src/wait_for_condition/wait_for_condition.py rename to packages/aws-durable-execution-sdk-python/examples/src/wait_for_condition/wait_for_condition.py diff --git a/examples/template.yaml b/packages/aws-durable-execution-sdk-python/examples/template.yaml similarity index 100% rename from examples/template.yaml rename to packages/aws-durable-execution-sdk-python/examples/template.yaml diff --git a/examples/test/README.md b/packages/aws-durable-execution-sdk-python/examples/test/README.md similarity index 100% rename from examples/test/README.md rename to packages/aws-durable-execution-sdk-python/examples/test/README.md diff --git a/examples/test/__init__.py b/packages/aws-durable-execution-sdk-python/examples/test/__init__.py similarity index 100% rename from examples/test/__init__.py rename to packages/aws-durable-execution-sdk-python/examples/test/__init__.py diff --git a/examples/test/block_example/test_block_example.py b/packages/aws-durable-execution-sdk-python/examples/test/block_example/test_block_example.py similarity index 100% rename from examples/test/block_example/test_block_example.py rename to packages/aws-durable-execution-sdk-python/examples/test/block_example/test_block_example.py diff --git a/examples/test/callback/test_callback_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_concurrency.py similarity index 100% rename from examples/test/callback/test_callback_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_concurrency.py diff --git a/examples/test/callback/test_callback_heartbeat.py b/packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_heartbeat.py similarity index 100% rename from examples/test/callback/test_callback_heartbeat.py rename to packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_heartbeat.py diff --git a/examples/test/callback/test_callback_mixed_ops.py b/packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_mixed_ops.py similarity index 100% rename from examples/test/callback/test_callback_mixed_ops.py rename to packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_mixed_ops.py diff --git a/examples/test/callback/test_callback_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_serdes.py similarity index 100% rename from examples/test/callback/test_callback_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_serdes.py diff --git a/examples/test/callback/test_callback_simple.py b/packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_simple.py similarity index 100% rename from examples/test/callback/test_callback_simple.py rename to packages/aws-durable-execution-sdk-python/examples/test/callback/test_callback_simple.py diff --git a/examples/test/comprehensive_operations/test_comprehensive_operations.py b/packages/aws-durable-execution-sdk-python/examples/test/comprehensive_operations/test_comprehensive_operations.py similarity index 100% rename from examples/test/comprehensive_operations/test_comprehensive_operations.py rename to packages/aws-durable-execution-sdk-python/examples/test/comprehensive_operations/test_comprehensive_operations.py diff --git a/examples/test/conftest.py b/packages/aws-durable-execution-sdk-python/examples/test/conftest.py similarity index 100% rename from examples/test/conftest.py rename to packages/aws-durable-execution-sdk-python/examples/test/conftest.py diff --git a/examples/test/handler_error/test_handler_error.py b/packages/aws-durable-execution-sdk-python/examples/test/handler_error/test_handler_error.py similarity index 100% rename from examples/test/handler_error/test_handler_error.py rename to packages/aws-durable-execution-sdk-python/examples/test/handler_error/test_handler_error.py diff --git a/examples/test/logger_example/test_logger_example.py b/packages/aws-durable-execution-sdk-python/examples/test/logger_example/test_logger_example.py similarity index 100% rename from examples/test/logger_example/test_logger_example.py rename to packages/aws-durable-execution-sdk-python/examples/test/logger_example/test_logger_example.py diff --git a/examples/test/map/test_map_completion.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_completion.py similarity index 100% rename from examples/test/map/test_map_completion.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_completion.py diff --git a/examples/test/map/test_map_operations.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_operations.py similarity index 100% rename from examples/test/map/test_map_operations.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_operations.py diff --git a/examples/test/map/test_map_operations_flat.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_operations_flat.py similarity index 100% rename from examples/test/map/test_map_operations_flat.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_operations_flat.py diff --git a/examples/test/map/test_map_with_batch_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_batch_serdes.py similarity index 100% rename from examples/test/map/test_map_with_batch_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_batch_serdes.py diff --git a/examples/test/map/test_map_with_custom_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_custom_serdes.py similarity index 100% rename from examples/test/map/test_map_with_custom_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_custom_serdes.py diff --git a/examples/test/map/test_map_with_failure_tolerance.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_failure_tolerance.py similarity index 100% rename from examples/test/map/test_map_with_failure_tolerance.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_failure_tolerance.py diff --git a/examples/test/map/test_map_with_item_namer.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_item_namer.py similarity index 100% rename from examples/test/map/test_map_with_item_namer.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_item_namer.py diff --git a/examples/test/map/test_map_with_large_scale.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_large_scale.py similarity index 100% rename from examples/test/map/test_map_with_large_scale.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_large_scale.py diff --git a/examples/test/map/test_map_with_max_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_max_concurrency.py similarity index 100% rename from examples/test/map/test_map_with_max_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_max_concurrency.py diff --git a/examples/test/map/test_map_with_min_successful.py b/packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_min_successful.py similarity index 100% rename from examples/test/map/test_map_with_min_successful.py rename to packages/aws-durable-execution-sdk-python/examples/test/map/test_map_with_min_successful.py diff --git a/examples/test/no_replay_execution/test_no_replay_execution.py b/packages/aws-durable-execution-sdk-python/examples/test/no_replay_execution/test_no_replay_execution.py similarity index 100% rename from examples/test/no_replay_execution/test_no_replay_execution.py rename to packages/aws-durable-execution-sdk-python/examples/test/no_replay_execution/test_no_replay_execution.py diff --git a/examples/test/none_results/test_none_results.py b/packages/aws-durable-execution-sdk-python/examples/test/none_results/test_none_results.py similarity index 100% rename from examples/test/none_results/test_none_results.py rename to packages/aws-durable-execution-sdk-python/examples/test/none_results/test_none_results.py diff --git a/examples/test/parallel/test_parallel.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel.py similarity index 100% rename from examples/test/parallel/test_parallel.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel.py diff --git a/examples/test/parallel/test_parallel_flat.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_flat.py similarity index 100% rename from examples/test/parallel/test_parallel_flat.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_flat.py diff --git a/examples/test/parallel/test_parallel_with_batch_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_batch_serdes.py similarity index 100% rename from examples/test/parallel/test_parallel_with_batch_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_batch_serdes.py diff --git a/examples/test/parallel/test_parallel_with_custom_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_custom_serdes.py similarity index 100% rename from examples/test/parallel/test_parallel_with_custom_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_custom_serdes.py diff --git a/examples/test/parallel/test_parallel_with_failure_tolerance.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_failure_tolerance.py similarity index 100% rename from examples/test/parallel/test_parallel_with_failure_tolerance.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_failure_tolerance.py diff --git a/examples/test/parallel/test_parallel_with_max_concurrency.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_max_concurrency.py similarity index 100% rename from examples/test/parallel/test_parallel_with_max_concurrency.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_max_concurrency.py diff --git a/examples/test/parallel/test_parallel_with_named_branches.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_named_branches.py similarity index 100% rename from examples/test/parallel/test_parallel_with_named_branches.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_named_branches.py diff --git a/examples/test/parallel/test_parallel_with_wait.py b/packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_wait.py similarity index 100% rename from examples/test/parallel/test_parallel_with_wait.py rename to packages/aws-durable-execution-sdk-python/examples/test/parallel/test_parallel_with_wait.py diff --git a/examples/test/run_in_child_context/test_run_in_child_context.py b/packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context.py similarity index 100% rename from examples/test/run_in_child_context/test_run_in_child_context.py rename to packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context.py diff --git a/examples/test/run_in_child_context/test_run_in_child_context_large_data.py b/packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context_large_data.py similarity index 100% rename from examples/test/run_in_child_context/test_run_in_child_context_large_data.py rename to packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context_large_data.py diff --git a/examples/test/run_in_child_context/test_run_in_child_context_step_failure.py b/packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context_step_failure.py similarity index 100% rename from examples/test/run_in_child_context/test_run_in_child_context_step_failure.py rename to packages/aws-durable-execution-sdk-python/examples/test/run_in_child_context/test_run_in_child_context_step_failure.py diff --git a/examples/test/simple_execution/test_simple_execution.py b/packages/aws-durable-execution-sdk-python/examples/test/simple_execution/test_simple_execution.py similarity index 100% rename from examples/test/simple_execution/test_simple_execution.py rename to packages/aws-durable-execution-sdk-python/examples/test/simple_execution/test_simple_execution.py diff --git a/examples/test/step/test_step.py b/packages/aws-durable-execution-sdk-python/examples/test/step/test_step.py similarity index 100% rename from examples/test/step/test_step.py rename to packages/aws-durable-execution-sdk-python/examples/test/step/test_step.py diff --git a/examples/test/step/test_step_permutations.py b/packages/aws-durable-execution-sdk-python/examples/test/step/test_step_permutations.py similarity index 100% rename from examples/test/step/test_step_permutations.py rename to packages/aws-durable-execution-sdk-python/examples/test/step/test_step_permutations.py diff --git a/examples/test/step/test_step_semantics_at_most_once.py b/packages/aws-durable-execution-sdk-python/examples/test/step/test_step_semantics_at_most_once.py similarity index 100% rename from examples/test/step/test_step_semantics_at_most_once.py rename to packages/aws-durable-execution-sdk-python/examples/test/step/test_step_semantics_at_most_once.py diff --git a/examples/test/step/test_step_with_retry.py b/packages/aws-durable-execution-sdk-python/examples/test/step/test_step_with_retry.py similarity index 100% rename from examples/test/step/test_step_with_retry.py rename to packages/aws-durable-execution-sdk-python/examples/test/step/test_step_with_retry.py diff --git a/examples/test/step/test_steps_with_retry.py b/packages/aws-durable-execution-sdk-python/examples/test/step/test_steps_with_retry.py similarity index 100% rename from examples/test/step/test_steps_with_retry.py rename to packages/aws-durable-execution-sdk-python/examples/test/step/test_steps_with_retry.py diff --git a/examples/test/test_hello_world.py b/packages/aws-durable-execution-sdk-python/examples/test/test_hello_world.py similarity index 100% rename from examples/test/test_hello_world.py rename to packages/aws-durable-execution-sdk-python/examples/test/test_hello_world.py diff --git a/examples/test/wait/test_multiple_wait.py b/packages/aws-durable-execution-sdk-python/examples/test/wait/test_multiple_wait.py similarity index 100% rename from examples/test/wait/test_multiple_wait.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait/test_multiple_wait.py diff --git a/examples/test/wait/test_wait.py b/packages/aws-durable-execution-sdk-python/examples/test/wait/test_wait.py similarity index 100% rename from examples/test/wait/test_wait.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait/test_wait.py diff --git a/examples/test/wait/test_wait_permutations.py b/packages/aws-durable-execution-sdk-python/examples/test/wait/test_wait_permutations.py similarity index 100% rename from examples/test/wait/test_wait_permutations.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait/test_wait_permutations.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_anonymous.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_anonymous.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_anonymous.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_anonymous.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_child.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_child.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_child.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_child.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_failure.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_failure.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_failure.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_failure.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_heartbeat.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_heartbeat.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_heartbeat.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_heartbeat.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_mixed_ops.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_mixed_ops.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_mixed_ops.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_mixed_ops.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_multiple_invocations.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_nested.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_nested.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_nested.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_nested.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_serdes.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_serdes.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_serdes.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_serdes.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_submitter_failure.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_submitter_failure_catchable.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_success.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_success.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_success.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_success.py diff --git a/examples/test/wait_for_callback/test_wait_for_callback_timeout.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_timeout.py similarity index 100% rename from examples/test/wait_for_callback/test_wait_for_callback_timeout.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_callback/test_wait_for_callback_timeout.py diff --git a/examples/test/wait_for_condition/test_wait_for_condition.py b/packages/aws-durable-execution-sdk-python/examples/test/wait_for_condition/test_wait_for_condition.py similarity index 100% rename from examples/test/wait_for_condition/test_wait_for_condition.py rename to packages/aws-durable-execution-sdk-python/examples/test/wait_for_condition/test_wait_for_condition.py diff --git a/pyproject.toml b/packages/aws-durable-execution-sdk-python/pyproject.toml similarity index 100% rename from pyproject.toml rename to packages/aws-durable-execution-sdk-python/pyproject.toml diff --git a/tests/__init__.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/.gitignore similarity index 100% rename from tests/__init__.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/.gitignore diff --git a/src/aws_durable_execution_sdk_python/__about__.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/__about__.py similarity index 100% rename from src/aws_durable_execution_sdk_python/__about__.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/__about__.py diff --git a/src/aws_durable_execution_sdk_python/__init__.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/__init__.py similarity index 100% rename from src/aws_durable_execution_sdk_python/__init__.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/__init__.py diff --git a/tests/e2e/__init__.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/__init__.py similarity index 100% rename from tests/e2e/__init__.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/__init__.py diff --git a/src/aws_durable_execution_sdk_python/concurrency/executor.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/executor.py similarity index 100% rename from src/aws_durable_execution_sdk_python/concurrency/executor.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/executor.py diff --git a/src/aws_durable_execution_sdk_python/concurrency/models.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/models.py similarity index 100% rename from src/aws_durable_execution_sdk_python/concurrency/models.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/concurrency/models.py diff --git a/src/aws_durable_execution_sdk_python/config.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/config.py similarity index 100% rename from src/aws_durable_execution_sdk_python/config.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/config.py diff --git a/src/aws_durable_execution_sdk_python/context.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/context.py similarity index 100% rename from src/aws_durable_execution_sdk_python/context.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/context.py diff --git a/src/aws_durable_execution_sdk_python/exceptions.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/exceptions.py similarity index 100% rename from src/aws_durable_execution_sdk_python/exceptions.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/exceptions.py diff --git a/src/aws_durable_execution_sdk_python/execution.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/execution.py similarity index 100% rename from src/aws_durable_execution_sdk_python/execution.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/execution.py diff --git a/src/aws_durable_execution_sdk_python/identifier.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/identifier.py similarity index 100% rename from src/aws_durable_execution_sdk_python/identifier.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/identifier.py diff --git a/src/aws_durable_execution_sdk_python/lambda_service.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/lambda_service.py similarity index 100% rename from src/aws_durable_execution_sdk_python/lambda_service.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/lambda_service.py diff --git a/src/aws_durable_execution_sdk_python/logger.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/logger.py similarity index 100% rename from src/aws_durable_execution_sdk_python/logger.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/logger.py diff --git a/src/aws_durable_execution_sdk_python/operation/__init__.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/__init__.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/__init__.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/__init__.py diff --git a/src/aws_durable_execution_sdk_python/operation/base.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/base.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/base.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/base.py diff --git a/src/aws_durable_execution_sdk_python/operation/callback.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/callback.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/callback.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/callback.py diff --git a/src/aws_durable_execution_sdk_python/operation/child.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/child.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/child.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/child.py diff --git a/src/aws_durable_execution_sdk_python/operation/invoke.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/invoke.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/invoke.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/invoke.py diff --git a/src/aws_durable_execution_sdk_python/operation/map.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/map.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/map.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/map.py diff --git a/src/aws_durable_execution_sdk_python/operation/parallel.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/parallel.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/parallel.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/parallel.py diff --git a/src/aws_durable_execution_sdk_python/operation/step.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/step.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/step.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/step.py diff --git a/src/aws_durable_execution_sdk_python/operation/wait.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/wait.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/wait.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/wait.py diff --git a/src/aws_durable_execution_sdk_python/operation/wait_for_condition.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/wait_for_condition.py similarity index 100% rename from src/aws_durable_execution_sdk_python/operation/wait_for_condition.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/operation/wait_for_condition.py diff --git a/src/aws_durable_execution_sdk_python/py.typed b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/py.typed similarity index 100% rename from src/aws_durable_execution_sdk_python/py.typed rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/py.typed diff --git a/src/aws_durable_execution_sdk_python/retries.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/retries.py similarity index 100% rename from src/aws_durable_execution_sdk_python/retries.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/retries.py diff --git a/src/aws_durable_execution_sdk_python/serdes.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/serdes.py similarity index 100% rename from src/aws_durable_execution_sdk_python/serdes.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/serdes.py diff --git a/src/aws_durable_execution_sdk_python/state.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/state.py similarity index 100% rename from src/aws_durable_execution_sdk_python/state.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/state.py diff --git a/src/aws_durable_execution_sdk_python/suspend.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/suspend.py similarity index 100% rename from src/aws_durable_execution_sdk_python/suspend.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/suspend.py diff --git a/src/aws_durable_execution_sdk_python/threading.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/threading.py similarity index 100% rename from src/aws_durable_execution_sdk_python/threading.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/threading.py diff --git a/src/aws_durable_execution_sdk_python/types.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/types.py similarity index 100% rename from src/aws_durable_execution_sdk_python/types.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/types.py diff --git a/src/aws_durable_execution_sdk_python/waits.py b/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/waits.py similarity index 100% rename from src/aws_durable_execution_sdk_python/waits.py rename to packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/waits.py diff --git a/tests/operation/__init__.py b/packages/aws-durable-execution-sdk-python/tests/__init__.py similarity index 100% rename from tests/operation/__init__.py rename to packages/aws-durable-execution-sdk-python/tests/__init__.py diff --git a/tests/concurrency_test.py b/packages/aws-durable-execution-sdk-python/tests/concurrency_test.py similarity index 100% rename from tests/concurrency_test.py rename to packages/aws-durable-execution-sdk-python/tests/concurrency_test.py diff --git a/tests/config_test.py b/packages/aws-durable-execution-sdk-python/tests/config_test.py similarity index 100% rename from tests/config_test.py rename to packages/aws-durable-execution-sdk-python/tests/config_test.py diff --git a/tests/context_test.py b/packages/aws-durable-execution-sdk-python/tests/context_test.py similarity index 100% rename from tests/context_test.py rename to packages/aws-durable-execution-sdk-python/tests/context_test.py diff --git a/tests/durable_executions_python_language_sdk_test.py b/packages/aws-durable-execution-sdk-python/tests/durable_executions_python_language_sdk_test.py similarity index 100% rename from tests/durable_executions_python_language_sdk_test.py rename to packages/aws-durable-execution-sdk-python/tests/durable_executions_python_language_sdk_test.py diff --git a/packages/aws-durable-execution-sdk-python/tests/e2e/__init__.py b/packages/aws-durable-execution-sdk-python/tests/e2e/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/e2e/checkpoint_response_int_test.py b/packages/aws-durable-execution-sdk-python/tests/e2e/checkpoint_response_int_test.py similarity index 100% rename from tests/e2e/checkpoint_response_int_test.py rename to packages/aws-durable-execution-sdk-python/tests/e2e/checkpoint_response_int_test.py diff --git a/tests/e2e/execution_int_test.py b/packages/aws-durable-execution-sdk-python/tests/e2e/execution_int_test.py similarity index 100% rename from tests/e2e/execution_int_test.py rename to packages/aws-durable-execution-sdk-python/tests/e2e/execution_int_test.py diff --git a/tests/e2e/map_with_concurrent_waits_int_test.py b/packages/aws-durable-execution-sdk-python/tests/e2e/map_with_concurrent_waits_int_test.py similarity index 100% rename from tests/e2e/map_with_concurrent_waits_int_test.py rename to packages/aws-durable-execution-sdk-python/tests/e2e/map_with_concurrent_waits_int_test.py diff --git a/tests/exceptions_test.py b/packages/aws-durable-execution-sdk-python/tests/exceptions_test.py similarity index 100% rename from tests/exceptions_test.py rename to packages/aws-durable-execution-sdk-python/tests/exceptions_test.py diff --git a/tests/execution_test.py b/packages/aws-durable-execution-sdk-python/tests/execution_test.py similarity index 100% rename from tests/execution_test.py rename to packages/aws-durable-execution-sdk-python/tests/execution_test.py diff --git a/tests/lambda_service_test.py b/packages/aws-durable-execution-sdk-python/tests/lambda_service_test.py similarity index 100% rename from tests/lambda_service_test.py rename to packages/aws-durable-execution-sdk-python/tests/lambda_service_test.py diff --git a/tests/logger_test.py b/packages/aws-durable-execution-sdk-python/tests/logger_test.py similarity index 100% rename from tests/logger_test.py rename to packages/aws-durable-execution-sdk-python/tests/logger_test.py diff --git a/packages/aws-durable-execution-sdk-python/tests/operation/__init__.py b/packages/aws-durable-execution-sdk-python/tests/operation/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/operation/base_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/base_test.py similarity index 100% rename from tests/operation/base_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/base_test.py diff --git a/tests/operation/callback_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/callback_test.py similarity index 100% rename from tests/operation/callback_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/callback_test.py diff --git a/tests/operation/child_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/child_test.py similarity index 100% rename from tests/operation/child_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/child_test.py diff --git a/tests/operation/invoke_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/invoke_test.py similarity index 100% rename from tests/operation/invoke_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/invoke_test.py diff --git a/tests/operation/map_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/map_test.py similarity index 100% rename from tests/operation/map_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/map_test.py diff --git a/tests/operation/parallel_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/parallel_test.py similarity index 100% rename from tests/operation/parallel_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/parallel_test.py diff --git a/tests/operation/step_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/step_test.py similarity index 100% rename from tests/operation/step_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/step_test.py diff --git a/tests/operation/wait_for_condition_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/wait_for_condition_test.py similarity index 100% rename from tests/operation/wait_for_condition_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/wait_for_condition_test.py diff --git a/tests/operation/wait_test.py b/packages/aws-durable-execution-sdk-python/tests/operation/wait_test.py similarity index 100% rename from tests/operation/wait_test.py rename to packages/aws-durable-execution-sdk-python/tests/operation/wait_test.py diff --git a/tests/retries_test.py b/packages/aws-durable-execution-sdk-python/tests/retries_test.py similarity index 100% rename from tests/retries_test.py rename to packages/aws-durable-execution-sdk-python/tests/retries_test.py diff --git a/tests/serdes_test.py b/packages/aws-durable-execution-sdk-python/tests/serdes_test.py similarity index 100% rename from tests/serdes_test.py rename to packages/aws-durable-execution-sdk-python/tests/serdes_test.py diff --git a/tests/state_test.py b/packages/aws-durable-execution-sdk-python/tests/state_test.py similarity index 100% rename from tests/state_test.py rename to packages/aws-durable-execution-sdk-python/tests/state_test.py diff --git a/tests/suspend_test.py b/packages/aws-durable-execution-sdk-python/tests/suspend_test.py similarity index 100% rename from tests/suspend_test.py rename to packages/aws-durable-execution-sdk-python/tests/suspend_test.py diff --git a/tests/test_helpers.py b/packages/aws-durable-execution-sdk-python/tests/test_helpers.py similarity index 100% rename from tests/test_helpers.py rename to packages/aws-durable-execution-sdk-python/tests/test_helpers.py diff --git a/tests/threading_test.py b/packages/aws-durable-execution-sdk-python/tests/threading_test.py similarity index 100% rename from tests/threading_test.py rename to packages/aws-durable-execution-sdk-python/tests/threading_test.py diff --git a/tests/types_test.py b/packages/aws-durable-execution-sdk-python/tests/types_test.py similarity index 100% rename from tests/types_test.py rename to packages/aws-durable-execution-sdk-python/tests/types_test.py diff --git a/tests/waits_test.py b/packages/aws-durable-execution-sdk-python/tests/waits_test.py similarity index 100% rename from tests/waits_test.py rename to packages/aws-durable-execution-sdk-python/tests/waits_test.py From ef37c9233dd2a637fe8a658b167229564c9fdffb Mon Sep 17 00:00:00 2001 From: hsilan Date: Fri, 22 May 2026 14:13:34 -0700 Subject: [PATCH 2/2] fix(ci): fix path to generate_same_template.py --- .github/workflows/update-sam-template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-sam-template.yml b/.github/workflows/update-sam-template.yml index 63bdde9a..70aa2e16 100644 --- a/.github/workflows/update-sam-template.yml +++ b/.github/workflows/update-sam-template.yml @@ -27,7 +27,7 @@ jobs: python-version: "3.13" - name: Generate SAM template - run: python examples/scripts/generate_sam_template.py + run: python packages/aws-durable-execution-sdk-python/examples/scripts/generate_sam_template.py - name: Commit and push changes run: |